6

foldlWithKey のような関数を探していますが、モナドにカプセル化されています。

タイプがあると思います

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

しかし、Hoogle は私にそのタイプのものを何も与えてくれません。

4

2 に答える 2

10

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と で不要な 2 つの を>>=取り除くことができます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
于 2015-04-04T16:28:31.197 に答える
7

@Cirdecのソリューションは確かに機能しますが、問題が発生する可能性があります.sが>>=左に深くネストされています。多くの (しかしすべてではない!) モナドでは、これにより non-strict を使用した場合と同様のスタックブローアップが発生する可能性がありますfoldl>>=そこで、代わりに s を右にネストする別の解決策を提示します。このようなモナド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
于 2015-04-04T18:13:27.243 に答える