質問
リストの要素間で論理的で機能する関数を書くにはどうすればよいですか?
私はこれを書いた:
iand :: [IO Bool] -> IO Bool
iand [] = return (True)
iand (x:xs) = do
a <- x
b <- iand(xs)
return (a && b)
しかし、それは無意識のようです。
この関数は、FoldM(LIFTM)でどのように書き直すことができますか?
ありがとうございました。
解決
プレリュード関数 and :: [Bool] -> Bool
ほぼあなたが望むことをしますが、それはモナディックではありません。一般的に言えば、1つのargument関数をモナドに持ち上げるには、control.monad'sが必要です。 liftM :: Monad m => (a -> b) -> m a -> b a
;ただし、より一般的にするには、プレリュードを使用できます fmap :: Functor f => (a -> b) -> f a -> f b
. 。すべてのモナドは機能者です1, 、これは大丈夫です。したがって、使用できます
fand' :: Functor f => f [Bool] -> f Bool
fand' = fmap and
しかし、少なくとも90%の時間、私はそのインラインを次のように書くだけです fmap and xs
, 、またはおそらく and <$> xs
, 、control.applicativeの使用 <$>
の同義語 fmap
.
もちろん、あなたが気づいたと確信しているように、これはあなたが望むものではありません。そのためには、プレリュードが必要です sequence :: Monad m => [m a] -> m [a]
. 。これで機能があります [m a] -> m [a]
, 、および関数 f [Bool] -> f Bool
, 、したがって、これらを組み合わせることができます:
mand :: Monad m => [m Bool] -> m Bool
mand = liftM and . sequence
に切り替えました liftM
から fmap
なぜなら、しかし fmap
ある意味で「より良い」、それは追加を課すでしょう Functor m
制約。それか すべきではありません 問題になりますが、それは歴史的な理由である可能性があるので、私はそれを安全にプレイしました。
また、あなたは尋ねるかもしれません」 sequence
「?それに対する答えは素晴らしいです フーグル, 、名前でHaskell関数を検索できるようにする または入力します. 。だから、あなたは知っていたので liftM :: Monad m => (a -> b) -> m a -> m b
, 、あなたはあなたがのようなものが必要であることに気づいたかもしれません Monad m => [m a] -> m [a]
;そのためのフーギリング 確かに現れます sequence
.
1: または、少なくとも、歴史的な理由のためにそうであるべきですが、これは常にそうではありません。
他のヒント
使用できます liftM
向きを変える and
(タイプがあります [Bool] -> Bool
)タイプの関数に IO [Bool] -> IO Bool
と sequence
あなたを回すために [IO Bool]
に IO [Bool]
.
だからあなたの機能は次のようになります:
iand ibs = liftM and (sequence ibs)
これはそうではないでしょう iand list = foldl (&&) True list
?