RnM*_*Mss 3 haskell lazy-evaluation
getText = do
c <- getChar
s <- getText
return (c : s)
main = do
s <- getText
putStr s
Run Code Online (Sandbox Code Playgroud)
我期望看到的是每次按下'Enter'后输入线都会被回显.但没有任何回应...(我知道这是一个无限循环)它似乎不会" return"直到它上面的所有"IO"执行....
但是,以下代码:
main = do
s <- getContents
putStr s
Run Code Online (Sandbox Code Playgroud)
它在输入后立即显示该行.
鉴于功能getChar,我可以写一个getText表现得像getContents?
这是...的工作unsafeInterleaveIO- 使懒惰IO成为可能的特殊操作.它允许您将IO操作转换为绑定到thunk的操作.然后可以将其存储在结构中,并且该操作仅评估何时需要其结果.
getText = unsafeInterleaveIO $ do
c <- getChar
s <- getText
return (c : s)
Run Code Online (Sandbox Code Playgroud)
现在,您getText只需为每个getChar暂停计算即可返回.如果您需要结果,则运行它.
这可以通过unsafeInterleaveIO函数
来完成System.IO.Unsafe.getText然后你的功能变成了
getText = do
c <- getChar
s <- unsafeInterleaveIO $ getText
return (c : s)
Run Code Online (Sandbox Code Playgroud)
稍微抽象一下,我们可以得到一个函数来推广这种行为
lazyDoIO :: IO a -> IO [a]
lazyDoIO act = unsafeInterleaveIO $ do
now <- act
rest <- lazyDoIO act
return (now : rest)
getText = lazyDoIO getChar
Run Code Online (Sandbox Code Playgroud)
然而,大多数Haskellers都会为此感到畏缩.如果你想对IO生成的数据进行增量流处理,那么使用像Pipes或的库会更安全Conduits.