我可以写以下内容:
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))
那我该如何打结呢?
澄清:
基本上,我希望
Int
的f
列表作为g2
的输入,而Int
的g2
列表作为f
的输入。 最佳答案
列表的有效概括是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
ListT
tutorial,尤其是section on pipes
了解有关ListT
的更多信息。关于haskell - 相互递归IO定义,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26622618/