Usted debe primero gire el [Maybe a]
en un Maybe [a]
con todos los elementos Just
(lo que supondría Nothing
si alguno de ellos es Nothing
). Esto se puede hacer usando sequence, utilizando lo mejor es ejemplo Mónada:
GHCi> sequence [Just 1, Just 2]
Just [1,2]
GHCi> sequence [Just 1, Just 2, Nothing]
Nothing
El definition of sequence es equivalente a la siguiente:
sequence [] = return []
sequence (m:ms) = do
x <- m
xs <- sequence ms
return (x:xs)
para que podamos ampliar este último ejemplo, como:
do x <- Just 1
xs <- do
y <- Just 2
ys <- do
z <- Nothing
zs <- return []
return (z:zs)
return (y:ys)
return (x:xs)
Usando el do-notation expression of the monad laws, podemos reescribir esto de la siguiente manera:
do x <- Just 1
y <- Just 2
z <- Nothing
return [x, y, z]
Si sabe cómo funciona Maybe Monada, ahora debe comprender cómo funciona sequence
para lograr el comportamiento deseado. :)
A continuación, puede componer esto con foldr
usando (<$>)
(de Control.Applicative; equivalentemente, fmap
o liftM
) a veces su función binaria sobre la lista:
GHCi> foldl' (+) 0 <$> sequence [Just 1, Just 2]
Just 3
Por supuesto, se puede utilizar cualquier usted doblar desee, como foldr
, etc. foldl1
como extra, si desea que el resultado sea Nothing
cuando la lista está vacía, y así poder omitir el valor cero del pliegue sin worr ying acerca de los errores en las listas vacías, a continuación, puede utilizar esta función doble:
mfoldl1' :: (MonadPlus m) => (a -> a -> a) -> [a] -> m a
mfoldl1' _ [] = mzero
mfoldl1' f (x:xs) = return $ foldl' f x xs
y lo mismo para foldr
, foldl
, etc. Tendrá que importar Control.Monad para esto.
Sin embargo, esto tiene que ser utilizado de forma ligeramente diferente:
GHCi> mfoldl1' (+) =<< sequence [Just 1, Just 2]
Just 3
o
GHCi> sequence [Just 1, Just 2] >>= mfoldl1' (+)
Just 3
Esto es porque, a diferencia de los otros pliegues, el tipo de resultado se ve como m a
en lugar de a
; es un vincular en lugar de un mapa.
¿Qué tal un "producto de mónada"? – adamse
No lo sé, es por eso que estoy preguntando. – Chris
He ampliado mi respuesta para que coincida con su pregunta actualizada. – ehird