getText = do
c <- getChar
s <- getText
return (c : s)
main = do
s <- getText
putStr s
我希望看到的是每次按“Enter”后输入线都会回显。
但没有任何回应...(我知道这是一个无限循环)
它似乎不会“return
”,直到它上面的所有“IO”都被执行。 ...
但是,以下代码:
main = do
s <- getContents
putStr s
输入后立即显示该行。
鉴于函数getChar
,我可以写一个行为类似于getText
的{{1}}吗?
答案 0 :(得分:8)
这是... unsafeInterleaveIO
的工作 - 使懒惰IO成为可能的特殊操作。它允许您将IO操作转换为绑定到thunk的操作。然后可以将其存储在结构中,并且该操作仅评估何时需要其结果。
getText = unsafeInterleaveIO $ do
c <- getChar
s <- getText
return (c : s)
现在你的getText
立即返回,每个getChar只有一个暂停的计算。如果您需要结果,则会运行。
答案 1 :(得分:7)
这可以通过unsafeInterleaveIO
函数来完成
System.IO.Unsafe
。然后您的getText
功能变为
getText = do
c <- getChar
s <- unsafeInterleaveIO $ getText
return (c : s)
稍微抽象一下,我们可以得到一个函数来推广这种行为
lazyDoIO :: IO a -> IO [a]
lazyDoIO act = unsafeInterleaveIO $ do
now <- act
rest <- lazyDoIO act
return (now : rest)
getText = lazyDoIO getChar
然而,大多数Haskellers都会为此感到畏缩。如果你想做
IO
生成的数据的增量流处理,会更安全
使用Pipes
或Conduits
等库。
答案 2 :(得分:1)
您谈论的是Enter,但不要在代码中进行检查。
试试这个:
getText = do
c <- getChar
if (c == '\n')
then return [c]
else do
s <- getText
return (c : s)
main = do
s <- getText
putStr s