【问题标题】:Mutually recursive IO definitions相互递归的 IO 定义
【发布时间】:2014-10-30 00:15:03
【问题描述】:

我可以这样写:

f :: [Int] -> [Int]
f x = 0:(map (+1) x)

g :: [Int] -> [Int]
g x = map (*2) x

a = f b
b = g a

main = print $ take 5 a

一切都很好(ideone)。

但是,假设我希望 g 做一些比乘以 2 更复杂的事情,比如向用户询问一个数字并添加它,如下所示:

g2 :: [Int] -> IO [Int]
g2 = mapM (\x -> getLine >>= (return . (+x) . read))

那我该怎么打结呢?

澄清:

基本上,我希望f 中的Ints 列表成为g2 的输入,g2 中的Ints 列表成为f 的输入。

【问题讨论】:

  • 你可能想从Control.Monad.Fix看mfix。
  • 您能否尝试更具体地说明您要究竟做什么?
  • 与示例完全相同,只是将g 替换为g2。

标签: haskell


【解决方案1】:

列表的有效泛化是ListT:

import Control.Monad
import Pipes

f :: ListT IO Int -> ListT IO Int
f x = return 0 `mplus` fmap (+ 1) x

g2 :: ListT IO Int -> ListT IO Int
g2 x = do
    n  <- x
    n' <- lift (fmap read getLine)
    return (n' + n)

a = f b
b = g2 a

main = runListT $ do
    n <- a
    lift (print n)
    mzero

您还可以通过一些额外的代码实现类似take 的功能:

import qualified Pipes.Prelude as Pipes

take' :: Monad m => Int -> ListT m a -> ListT m a
take' n l = Select (enumerate l >-> Pipes.take n)

main = runListT $ do
    n <- take' 5 a
    lift (print n)
    mzero

示例会话:

>>> main
0
1<Enter>
2
2<Enter>
3<Enter>
7
4<Enter>
5<Enter>
6<Enter>
18
7<Enter>
8<Enter>
9<Enter>
10<Enter>
38

您可以通过reading the pipes tutorial(尤其是section on ListT)了解有关ListT 的更多信息。

【讨论】:

    猜你喜欢
    • 2011-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-11
    • 2011-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多