Я написал это для того, чтобы рано разорвать монадическую складку:
myfoldM :: (Monad m) => (a -> b -> m (Maybe a)) -> a -> [b] -> m (Maybe a)
myfoldM _ a [] = return $ Just a
myfoldM f a (x:xs) = do ma <- f a x;
case ma of
Nothing -> return Nothing
Just a' -> myfoldM f a' xs
и мне интересно, есть ли более элегантный способ выразить это или что-то подобное существует в библиотеке. Конечно, есть аналогичная версия, заменяющая Maybe
на Either
.
Обновление... вот полное решение на основе ответа Петра Пудлака:
import Control.Monad (foldM,Monad,mzero)
import Control.Monad.Trans.Maybe (MaybeT(..))
import Control.Monad.Trans.Class (lift)
myfoldM' :: (Monad m) => (a -> b -> MaybeT m a) -> a -> [b] -> m (Maybe a)
myfoldM' f = (runMaybeT .) . foldM f
go :: Int -> Int -> MaybeT IO Int
go s i = do
lift $ putStrLn $ "i = " ++ show i
if i <= 4 then return (s+i) else mzero
test n = do
myfoldM' go 0 [1..n] >>= print
-- test 3 => Just 6
-- test 5 => Nothing