Эта функция уже существует в sequence :: Monad m => [m a] -> m [a]
< /strong> функция:
Prelude> import Control.Monad
Prelude Control.Monad> sequence [Just 3]
Just [3]
Prelude Control.Monad> sequence [Just 3, Nothing]
Nothing
Prelude Control.Monad> sequence [Just 3, Just 2]
Just [3,2]
Prelude Control.Monad> sequence [Just 1,Just 2,Just 3,Just 4,Just 5]
Just [1,2,3,4,5]
Prelude Control.Monad> sequence [Just 1,Nothing,Just 3,Just 4,Just 5]
Nothing
По сути, это просто mapM id :: (Monad m, Traversable t) => t (m a) -> m (t a)
, так как, например, для 3-списка он равен:
-- special case for 3 elements to demonstrate how it works
func3 [a, b, c] = do
ya <- a
yb <- b
yc <- c
return [ya, yb, yc]
или таким образом:
func3 [a, b, c] = a >>= \ya -> b >>= \yb -> c >>= yc -> return [ya, yb, yc]
(Здесь я использую особый случай, так как mapM
вводит некоторые дополнительные функции, затрудняющие отслеживание)
Поскольку для Maybe
Monad Maybe
реализовано так:
instance Monad Maybe where
return = Just
Nothing >>= _ = Nothing
(Just x) >>= f = f x
так что это означает, что с момента, когда один из элементов (a
, b
или c
) равен Nothing
, результатом будет Nothing
, если все значения равны Just
s, мы «соберем» их с помощью лямбда-выражения и в конечном итоге получим список с элементы.
Вы можете видеть список []
как обобщение Maybe
(где Nothing
— пустой список, а Just
— одноэлементный список), и можно наблюдать такое же поведение:
Prelude Control.Monad> sequence [[1,2], [4,3]]
[[1,4],[1,3],[2,4],[2,3]]
Prelude Control.Monad> sequence [[1,2], [4,3], []]
[]
Здесь sequence
создаст перекрестное произведение, но если один из списков, содержащих элементы одного из множества, к которому применяется перекрестное произведение, пуст, то и результат будет пустым.
person
Willem Van Onsem
schedule
20.09.2018