Я не думаю, что синтаксис понимания списка имеет непосредственное отношение к тому факту, что List ([]
), или Maybe
в этом отношении, оказывается экземпляром класса Monad
.
Списочные выражения действительно магия компилятора или синтаксис sugar , но это возможно, потому что компилятор знает структуру типа данных []
.
Вот для чего составлено понимание списка: (Ну, я думаю, я на самом деле не проверял его по GHC)
xs = let f = \xs -> case xs of
Just x -> [x]
_ -> []
in concatMap f myList
Как видите, компилятору не нужно вызывать функцию fail
, он может просто вставить пустой список, потому что он знает, что такое список .
Интересно, что тот факт, что синтаксис списочных пропусков «пропускает» сбои сопоставления с образцом, используется в некоторых библиотеках для общего программирования. См. Пример в библиотеке Uniplate .
Редактировать: О, и чтобы ответить на ваш вопрос, вы не можете вызвать вашу функцию select
с лямбда, которую вы дали. Он действительно потерпит неудачу при ошибке сопоставления с образцом, если вы вызовете его со значением Nothing
.
Вы можете передать ей функцию f
из приведенного выше кода, но select
будет иметь тип:
select :: (a -> [b]) -> [a] -> [b]
, что прекрасно, вы можете использовать функцию concatMap
внутри: -)
Кроме того, этот новый select
теперь имеет тип оператора монадического связывания для списков (с перевернутыми аргументами):
(>>=) :: [a] -> (a -> [b]) -> [b]
xs >>= f = concatMap f xs -- 'or as you said: concat (map f xs)