2012-01-18 5 views
7

モナドはどのようにして1倍になりますか? Data.Foldableは厳密なfoldl'とモナディックfoldlMを持っていますが、厳密なものはありませんfoldlM'?厳密さは、モナド自体によって何とか定義されていますか?もしそうなら、どのようにしてそれがうまくいくのでしょうか?HaskellにfoldlM 'はありますか?

巨大なリング要素のリストの製品がゼロであるが、私のリングが整数ドメインではない、つまりゼロデバイスが含まれているかどうかを判断する必要があるとします。この場合、私は尾を再帰的にfoldl私の乗算***リスト上にする必要がありますが、False製品が完全な製品を待つよりゼロになる瞬間を返します。

safelist :: [p] -> Bool 
safelist [] = True 
safelist (x:xs) = snd $ foldl' f (x,True) xs 
    where f (u,b) v = (w, b && w /= Zero) where w = u *** v 

私は多分少しMaybeモナドのfoldlMを使用しますが、一見、必要な厳しさに欠けそう、このコードを簡素化することができます。

答えて

8

にはそのような標準機能はありませんが、定義するのは簡単です:

foldM' :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a 
foldM' _ z [] = return z 
foldM' f z (x:xs) = do 
    z' <- f z x 
    z' `seq` foldM' f z' xs 

これは単なる標準foldMですが、同じseqfoldl'が(foldlに比べて)んので、それにINGの。大部分のモナドでは、(>>=)は、スタックをあふれさせずに左折を使う必要があるという意味で厳密です。これは、過剰なサンクが返された値そのものにある場合にのみ役に立ちますが、foldMの便利なアプリケーションでは、最後のステップの値でモナド計算を実行することはありそうにありません。

私はあなたのコードがそのまま単純だと思います。私はfoldM'がこれ以上優雅になるとは思わない。

+0

ああ、厳密なフラグがあればモナドは厳格にすることができますが、それ以外の場合はできません。そして標準的なモナドはそうしません。ありがとう! –

+3

@JeffBurdges - ここでは、Monadicの '' = 'が厳しく対怠惰なアドホックな観測が​​あります:http://stackoverflow.com/a/8250334/208257 –

+0

確かに 'foldM''はあなたの '(>> =)'はあまりにも怠惰です。怠惰な 'State'モナドによって返された値を強制的に強制的に状態にするわけではありません。 – ehird

関連する問題