Haskell: [IO ()] 转换为 IO ()

5

Haskell维基有以下问题:

https://en.wikibooks.org/wiki/Haskell/Higher-order_functions for :: a -> (a -> Bool) -> (a -> a) -> (a -> IO ()) -> IO () for i p f job = -- ???

我能想到以下实现:

generate :: a -> (a->Bool) -> (a->a) -> [a]
generate s cnd incr = if (cnd s) then [] else [s] ++ generate (incr s) cnd incr

-- collapse :: [IO ()] -> IO ()
-- collapse (x:xs) = x ++ collapse xs
-- does not work ^^^^^^


for::a->(a->Bool)->(a->a)->(a->IO())->IO()
for s cnd incr ioFn = map (ioFn) (generate s cnd incr)

当然,map (ioFn) (generate s cnd incr)的结果是[IO ()]。我不确定如何将其转换为IO ()。我需要类似于foldl但是使用[IO ()]而不是[a]的函数。

1
你可以使用 sequence_ - Willem Van Onsem
2
generate s cnd incr = takeWhile cnd (iterate incr s) - 4castle
4
[IO ()][a]的一个更具体的实例(其中aIO ()),因此您可以将其传递给foldl。另外,您可以在https://hoogle.haskell.org/?hoogle=%5BIO%20()%5D%20-%3E%20IO%20()&scope=set%3Ahaskell-platform上提出这种类型的问题。 - jberryman
1
除了 sequence_,你可以直接使用例如 foldr (*>) (pure ())(或者 foldr (>>) (return ()))来编写这个函数。这基本上就是 sequence/sequence_/sequenceA 的实现方式:使用 applicative/monadic sequencing (*>/>>) 来连接这些操作,而“base case”则是一个什么都不做的操作 (pure ()/return ())。 - Jon Purdy
1个回答

10
你需要的功能是:

您正在寻找的功能是:

<b><a rel="noreferrer" href="https://hackage.haskell.org/package/base-4.12.0.0/docs/Prelude.html#v:sequence_">sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()</a></b>

但实际上我们可以直接替换 map,这样就不需要额外的函数了。你可以使用mapM_ :: Monad m => (a -> m b) -> [a] -> m () 代替 map,所以:

for :: a -> (a -> Bool) -> (a -> a) -> (a -> IO ()) -> IO()
for s cnd incr ioFn = <b>mapM_</b> ioFn (generate s cnd incr)

这将对generate s cnd incr中的所有元素应用函数ioFun,最终返回单元()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接