Вы должны сначала превращающие [Maybe a]
в Maybe [a]
со всеми Just
элементов (приносящих Nothing
, если любой из них Nothing
). Это может быть сделано с помощью sequence, используя Может это Монада пример:
GHCi> sequence [Just 1, Just 2]
Just [1,2]
GHCi> sequence [Just 1, Just 2, Nothing]
Nothing
definition of sequence эквивалентно следующему:
sequence [] = return []
sequence (m:ms) = do
x <- m
xs <- sequence ms
return (x:xs)
Таким образом, мы можем расширить последний пример, как:
do x <- Just 1
xs <- do
y <- Just 2
ys <- do
z <- Nothing
zs <- return []
return (z:zs)
return (y:ys)
return (x:xs)
Используя do-notation expression of the monad laws, мы можем переписать это следующим образом:
do x <- Just 1
y <- Just 2
z <- Nothing
return [x, y, z]
Если вы знаете, как работает монада Maybe, вы должны теперь понять, как работает sequence
для достижения желаемого поведения. :)
Вы можете составить это с помощью foldr
(<$>)
(от Control.Applicative, что то же самое, fmap
или liftM
), чтобы сложить бинарную функцию по списку:
GHCi> foldl' (+) 0 <$> sequence [Just 1, Just 2]
Just 3
Конечно, вы можете использовать любой сгиб вас хотите, например, foldr
, foldl1
и т.д.
в качестве дополнительного, если вы хотите, чтобы результат Nothing
, когда список пуст, и, таким образом, иметь возможность опускать значение сгиба нуля без Worr инь об ошибках на пустых списках, то вы можете использовать эту функцию кратную:
mfoldl1' :: (MonadPlus m) => (a -> a -> a) -> [a] -> m a
mfoldl1' _ [] = mzero
mfoldl1' f (x:xs) = return $ foldl' f x xs
и аналогично для foldr
, foldl
и т.д. Вам нужно импортировать Control.Monad для этого.
Однако, это должно быть использовано несколько иначе:
GHCi> mfoldl1' (+) =<< sequence [Just 1, Just 2]
Just 3
или
GHCi> sequence [Just 1, Just 2] >>= mfoldl1' (+)
Just 3
Это происходит потому, что, в отличие от других складок, тип результата выглядит m a
вместо a
; это bind, а не map.
Как насчет «продукта монады»? – adamse
Я не знаю, вот почему я спрашиваю. – Chris
Я расширил свой ответ, чтобы соответствовать вашему обновленному вопросу. – ehird