foldlWithKey в монаде

Я ищу функцию, которая похожа на foldlWithKey, но заключена в монаду.

Я ожидаю, что это будет иметь тип

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

но Google не дает мне ничего с этим типом.

2 ответа

Решение

foldlWithKey уже очень близко к тому, что вы хотите. Если вы специализируетесь a в m a у вас будет что-то, что работает со значениями, инкапсулированными в монаду.

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

Мы можем избавиться от двух m aты не хочешь с >>= а также return,

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

Решение @Cirdec, безусловно, работает, но у него есть возможная проблема: он гнездится >>=с глубоко влево. Для многих (но не всех!) Монад это может привести к разрушению стека, как при использовании нестрогих foldl, Поэтому я представлю другое решение, которое гнездится >>=вместо этого. Для монад, таких как IO это должно позволить построению действия и лениво потребляться с карты, когда оно выполняется.

Это решение, вероятно, немного сложнее, поскольку оно использует правильное сгиб для построения монадической функции, которая в конечном итоге будет использовать начальное значение. По крайней мере, у меня были некоторые проблемы с правильными типами.

За исключением обработки ключей, это по сути тот же метод, который используется Data.Foldable.foldlM,

-- 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 m a k b. Monad m => (a -> k -> b -> m a) -> a -> Map k b -> m a
foldlWithKeyM f start m = foldrWithKey f' return m $ start
  where
    f' :: k -> b -> (a -> m a) -> (a -> m a)
    f' k b a2mb a = f a k b >>= a2mb
Другие вопросы по тегам