Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lifting foldr to monad

I have function smallStep :: Command -> Data -> Either StepError Data, and I would like to make bigStep :: [Command] -> Data -> Either StepError Data using it, with following semantic:

bigStep []   data   = Right data
bigStep c:cs data   = do
               data' <- bigStep cs data
               smallStep c data'

It's nothing convoluted, but if smallStep had type Command -> Data -> Data, I would implement bigStep simply as bigStep commands data = foldr data smallStep commands.

Naturally, I would like to use foldr here as well. How do I do this? foldM is lifted foldl, and reversing list doesn't sound like a terribly good idea.

like image 654
Joker_vD Avatar asked Oct 16 '25 13:10

Joker_vD


1 Answers

In general, a left fold won't be better or worse than a right fold in terms of resource usage. However, I would assume that [Command] is supposed to be a list of sequenced commands intended to be executed one after another in the order they are supplied. If that is the case, it is probably easiest to build these lists backwards to begin with (instead of reversing them - this is indeed a costly operation for long lists). If you don't want to do that, here is a general monadic right fold:

foldrM :: Monad m => (a -> b -> m b) -> b -> [a] -> m b
foldrM f d []     = return d
foldrM f d (x:xs) = (\z -> f x z) =<< foldrM f d xs

Note the types of all the following :

foldl :: (a -> b -> a) -> a -> [b] -> a
foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a

foldr :: (a -> b -> b) -> b -> [a] -> b
foldrM :: Monad m => (a -> b -> m b) -> b -> [a] -> m b

We can deduce that foldrM is indeed a right fold.

However, if you need to fold a very large list, both of the monadic folds above are lazy and will only begin evaluation once the last function application is sequenced.

like image 180
user2407038 Avatar answered Oct 19 '25 14:10

user2407038



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!