質問

リストの要素間で論理的で機能する関数を書くにはどうすればよいですか?

私はこれを書いた:

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 Boolsequence あなたを回すために [IO Bool]IO [Bool].

だからあなたの機能は次のようになります:

iand ibs = liftM and (sequence ibs)

これはそうではないでしょう iand list = foldl (&&) True list ?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top