Ваше понимание списка - это, по сути, просто синтаксический сахар для:
import Control.Monad(guard)
boomBangs :: Integral i => [i] -> [String]
boomBangs xs = do
x <- xs
guard (odd x)
return (if x < 10 then "BOOM!" else "BANG!")
Таким образом, это do
выражение [отчет Haskell], и как говорится в отчете, это синтаксический сахар. Это синтаксический сахар для:
boomBangs xs = xs >>= \x -> (guard (odd x) >> return (if x < 10 then "BOOM!" else "BANG!"))
Для списка экземпляр Monad
определяется как:
instance Monad [] where
(>>=) = flip concatMap
return x = [x]
Кроме того, guard
определяется как:
guard :: Monad m => Bool -> m ()
guard True = pure ()
guard False = empty
и реализация (>>)
по умолчанию:
(>>) :: Monad m => m a -> m b -> m b
(>>) u v = u >>= \_ -> v
Таким образом, boomBangs
в основном реализуется как:
boomBangs xs = concatMap (\x -> (guard (odd x) >>= \_ -> [if x < 10 then "BOOM!" else "BANG!"])) xs
= concatMap (\x -> concatMap (\_ -> [if x < 10 then "BOOM!" else "BANG!"]) guard (odd x)) xs
Так как для списка guard
может быть специализирован для:
-- guard for the Monad []
guard :: Bool -> [()]
guard True = [()]
guard False = []
Таким образом, это означает, что если guard
получает True
, он возвращает одноэлементный список, а для False
пустой список. Таким образом, это означает, что если охранник удерживает, concatMap (\_ -> [if x < 10 then "BOOM!" else "BANG!"])
вернет содержимое в [if x < 10 then "BOOM!" else "BANG!"]
, если охранник не сработает, он вернет пустой список. Таким образом, охрана действует как своего рода фильтр.
Итак, что же такое x <-
. Если мы посмотрим, как do
-выражения обесахариваются, x <- foo
соответствует foo >>= \x -> ...
.
Для понимания списков x <- ...
действует как своего рода «перечислитель»: он будет перечислять все элементы в списке, а x
каждый раз будет получать один из элементов в списке для дальнейшей обработки.
person
Willem Van Onsem
schedule
12.08.2019
do
, который является синтаксическим сахаром для некоторых выражений с привязками. - person Willem Van Onsem   schedule 12.08.2019xs
в левой части — это аргумент функции, а в правой — фактическое определение функции. Это ничем не отличается отf x = x + 3
. В этом случае оператор<-
просто означает брать последовательные значения из спискаxs
и вызывать их каждоеx
по мере прохождения цикла. - person Andrew Jaffe   schedule 12.08.2019<-
на самом деле не оператор; это просто часть синтаксиса понимания списка. - person chepner   schedule 12.08.2019xs
справа от=
(переменная) относится кxs
слева (т.е. параметруboomBangs
). - person Will Ness   schedule 12.08.2019