Haskell: список понимания для комбинатора - PullRequest
8 голосов
/ 10 августа 2011

Вдохновленный этой статьей . Я играл с функциями перевода от понимания списка до комбинаторного стиля. Я нашел что-то интересное.

-- Example 1: List Comprehension 
*Main> [x|(x:_)<-["hi","hello",""]]
"hh"

-- Example 2: Combinatory
*Main> map head ["hi","hello",""]
"hh*** Exception: Prelude.head: empty list

-- Example 3: List Comprehension (translated from Example 2)
*Main> [head xs|xs<-["hi","hello",""]]
"hh*** Exception: Prelude.head: empty list 

Кажется странным, что пример 1 не вызывает исключение, потому что шаблон (x:_) соответствует одному из определений head. Подразумевается ли filter (not . null) при использовании списочных представлений?

Ответы [ 3 ]

7 голосов
/ 10 августа 2011

Ошибки сопоставления с образцом обрабатываются специально в списках.Если шаблон не совпадает, элемент удаляется.Следовательно, вы просто получаете "hh", но ничего для третьего элемента списка, так как элемент не соответствует шаблону.

Это связано с определением функции fail, которая вызывается из спискав случае, если шаблон не соответствует некоторому элементу:

fail _ = []

Правильные части этого ответа предоставлены kmc или #haskell славой.Все ошибки мои, не вините его.

7 голосов
/ 10 августа 2011

См. Раздел по спискам в отчете Haskell.Таким образом, в основном

[x|(x:_)<-["hi","hello",""]]

переводится как

let ok (x:_) = [ x ]
    ok _     = [ ]
in concatMap ok ["hi","hello",""]

PS Поскольку списочные выражения можно преобразовать в выражения do, то же самое происходит с выражениями do, как подробно описано в раздел о выражениях do .Таким образом, следующее также даст тот же результат:

do (x:_)<-["hi","hello",""]
   return x
6 голосов
/ 10 августа 2011

Да.Когда вы квалифицируете понимание списка путем сопоставления с образцом, значения, которые не совпадают, отфильтровываются, избавляясь от пустого списка в вашем Примере 1. В Примере 3 пустой список соответствует шаблону xs, поэтому не фильтруется,тогда head xs терпит неудачу.Точка сопоставления с образцом - это безопасное сочетание различения конструкторов и выбора компонентов!

Вы можете добиться того же сомнительного эффекта с шаблоном неопровержимый , лениво выполняя выбор без различения.

Prelude> [x|(~(x:_))<-["hi","hello",""]]
"hh*** Exception: <interactive>:1:0-30: Irrefutable pattern failed for pattern (x : _)

Список пониманий аккуратно использует пакет map, concat и, следовательно, filter.

...