如何编写列表元素之间逻辑和函数的函数?

我写了这一点:

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 几乎可以做您想要的,但这不是单一的。一般来说,要将单题功能提升到单片中,您需要控制。 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's <$> 同义词 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

我切换了 liftMfmap 因为,虽然 fmap从某种意义上说,“更好”的 Functor m 约束。那 不应该 成为一个问题,但可能是出于历史原因,所以我安全地玩了。

另外,您可能会问:“我将如何了解 sequence“?答案是美妙的 霍格, ,这使您可以按名称搜索Haskell功能 或类型. 。所以,既然你知道 liftM :: Monad m => (a -> b) -> m a -> m b, ,您可能已经意识到您需要类似的东西 Monad m => [m a] -> m [a];为此 确实出现了 sequence.


1: 或者,至少应该是 - 出于历史原因,并非总是如此。

其他提示

您可以使用 liftMand (有类型 [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