Haskell IO Bool 折叠问题
如何编写一个在列表元素之间执行逻辑和功能的函数?
我是这样写的:
iand :: [IO Bool] -> IO Bool
iand [] = return (True)
iand (x:xs) = do
a <- x
b <- iand(xs)
return (a && b)
但这似乎是不良心的。
如何用foldM(liftM)重写这个函数?
谢谢。
How can I write a function that does logical and function between the elements of the list?
I have written this:
iand :: [IO Bool] -> IO Bool
iand [] = return (True)
iand (x:xs) = do
a <- x
b <- iand(xs)
return (a && b)
But that seems to be unconscice.
How can this function be rewritten with foldM (liftM)?
Thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Prelude 函数
和 :: [布尔] -> Bool
几乎可以满足您的要求,但它不是单子。一般来说,要将单参数函数提升为 monad,您需要 Control.Monad 的liftM :: Monad m => (a→b)→妈-> b a
;但是,更一般地说,您可以使用 Prelude 的fmap :: 函子 f => (a→b)→发-> fb
。所有 monad 都是函子1,所以这是可以的。因此,您可以使用然而,至少 90% 的时间,我只是将内联编写为
fmap 和 xs
,或者更可能的是and <$>; xs
,使用 Control.Applicative 的<$>
是fmap
的同义词。当然,我相信您已经注意到,这不是您想要的。为此,您需要 Prelude 的
序列:: Monad m => [ma]-> m [a]
。你现在有一个函数[ma] -> m [a]
和函数f [Bool] -> f Bool
,所以我们可以将这些结合起来:我从
fmap
切换到liftM
,因为尽管fmap
在从某种意义上说,它会施加一个额外的函子 m 约束。这不应该是一个问题,但这可能是由于历史原因,所以我谨慎行事。另外,您可能会问“我怎么会知道
序列
”?答案是精彩的 Hoogle,它允许您按名称搜索 Haskell 函数或输入。所以,既然你知道liftM :: Monad m =>; (a→b)→妈-> m b
,您可能已经意识到您需要类似Monad m =>; [ma]-> m[a]
;寻找那个 确实出现了序列
。1:或者,至少,它们应该是这样的——但由于历史原因,情况并非总是如此。
The Prelude function
and :: [Bool] -> Bool
almost does what you want, but it's not monadic. Generally speaking, to lift a one-argument function into a monad, you'll want Control.Monad'sliftM :: Monad m => (a -> b) -> m a -> b a
; however, to be more general, you can use the Prelude'sfmap :: Functor f => (a -> b) -> f a -> f b
. All monads are functors1, so this is ok. Thus, you can useHowever, at least 90% of the time, I would just write that inline as
fmap and xs
, or more probablyand <$> xs
, using Control.Applicative's<$>
synonym forfmap
.Of course, as I'm sure you noticed, this isn't what you want. For that, you need the Prelude's
sequence :: Monad m => [m a] -> m [a]
. You now have a function[m a] -> m [a]
, and a functionf [Bool] -> f Bool
, so we can combine these:I switched to
liftM
fromfmap
because, althoughfmap
's "nicer" in some sense, it would impose an additionalFunctor m
constraint. That shouldn't be a problem, but it could be for historical reasons, so I played it safe.Also, you might ask "How would I have ever known about
sequence
"? The answer to that is the wonderful Hoogle, which allows you to search for Haskell functions by name or type. So, since you knew aboutliftM :: Monad m => (a -> b) -> m a -> m b
, you might have realized you needed something likeMonad m => [m a] -> m [a]
; Hoogling for that does indeed turn upsequence
.1: Or, at least, they should be—for historical reasons, though, this isn't always the case.
您可以使用
liftM
将and
(其类型为[Bool] -> Bool
)转换为IO 类型的函数 [布尔]-> IO Bool
和sequence
将您的[IO Bool]
转换为IO [Bool]
。所以你的函数就变成了:
You can use
liftM
to turnand
(which has type[Bool] -> Bool
) into a function of typeIO [Bool] -> IO Bool
andsequence
to turn your[IO Bool]
into anIO [Bool]
.So your function becomes:
这不是
iand list = Foldl (&&) True list
吗?Wouldn't this be
iand list = foldl (&&) True list
?