FoldlWithKey in Monad

I am looking for a function similar to foldlWithKey but encapsulated in a monad.

I expect it to be of type

Monad m => (a -> k -> b -> ma) -> a -> Map kb -> ma 

but Hoogle doesn't give me anything of this type.

+6
source share
2 answers

foldlWithKey already very close to what you want. If you specialize in a ma , you will have something that works with values ​​enclosed in a monad.

 foldlWithKey :: ( a -> k -> b -> a) -> a -> Map kb -> a foldlWithKey :: (ma -> k -> b -> ma) -> ma -> Map kb -> ma {- ^- you don't want these -^ -} 

We can get rid of two ma that you do not need with >>= and return .

 foldlWithKeyM :: Monad m => (a -> k -> b -> ma) -> a -> Map kb -> ma foldlWithKeyM f acc = foldlWithKey f' (return acc) where f' ma kb = ma >>= \a -> fakb 
+10
source

@Cirdec's solution certainly works, but it has a possible problem: it nests >>= deep to the left. For many (but not for all!) Monads, this can lead to a stack break similar to using a foldl . Therefore, I will present another solution, which instead of >>= will be placed on the right. For monads, such as IO , this should allow you to build an action and consume lazily from the card as it progresses.

This solution is probably a little more complicated as it uses the correct fold to create a monadic function that will eventually consume the initial value. At least I had problems with the correct types.

With the exception of key processing, this is essentially the same method that Data.Foldable.foldlM uses.

 -- Pragma needed only to give f' a type signature for sanity. Getting it -- right almost took a piece of mine until I remembered typed holes. {-# LANGUAGE ScopedTypeVariables #-} import Data.Map foldlWithKeyM :: forall mak b. Monad m => (a -> k -> b -> ma) -> a -> Map kb -> ma foldlWithKeyM f start m = foldrWithKey f' return m $ start where f' :: k -> b -> (a -> ma) -> (a -> ma) f' kb a2mb a = fakb >>= a2mb 
+7
source

Source: https://habr.com/ru/post/984684/


All Articles