haskell中的惰性IO:如何返回由某个阻塞IO生成的惰性列表?

haskell中的惰性IO:如何返回由某个阻塞IO生成的惰性列表?,haskell,lazy-evaluation,Haskell,Lazy Evaluation,它在输入后立即显示行 给定函数getChar,我可以编写一个类似于getContents的getText吗?这可以通过 System.IO.Unsafe。然后,您的getText函数变为 main = do s <- getContents putStr s getText=do 这是一份……的工作使懒惰IO成为可能的特殊操作。它允许您将IO操作转换为绑定到thunk的操作。然后可以将其存储在一个结构中,并且该操作仅在需要其结果时才进行评估 lazyDoIO :: IO

它在输入后立即显示行


给定函数
getChar
,我可以编写一个类似于
getContents
getText
吗?

这可以通过
System.IO.Unsafe
。然后,您的
getText
函数变为

main = do
    s <- getContents
    putStr s
getText=do
这是一份……的工作使懒惰IO成为可能的特殊操作。它允许您将IO操作转换为绑定到thunk的操作。然后可以将其存储在一个结构中,并且该操作仅在需要其结果时才进行评估

lazyDoIO :: IO a -> IO [a]
lazyDoIO act = unsafeInterleaveIO $ do
    now <- act
    rest <- lazyDoIO act
    return (now : rest)

getText = lazyDoIO getChar
getText=unsafeInterleaveIO$do

c您谈论Enter,但没有在代码中检查它

试试这个:

getText = unsafeInterleaveIO $ do
    c <- getChar
    s <- getText
    return (c : s)
getText=do

c不需要手动检查:在大多数控制台中,您正在键入的行在生效之前存储在行缓冲区中(以便您可以使用backspace或其他方法来修改它),直到您按下“Enter”键。但是您不能假装{putStr s}如果您放置一个无限循环以获得s值,则正在进行评估我已经看到了unsafeInterleaveIO效应(在Don Stewart提案中),但是程序不会终止!在{putStr s}之后用Ctrl-zadding关闭stdin之前,一个额外的{putStrLn“Done”}永远不会被打印出来。我正在使用它将一些API打包到一些更具功能的方法中。。。(因为我不太喜欢被动…@DonStewart你的评论是什么意思?在某些情况下,您会推荐惰性IO(ve)r迭代器/管道吗?我想说的是,仅仅因为某些东西(懒惰IO)已经使用了很多年,并不意味着它是解决问题的好方法……我认为你不应该对懒惰IO“畏缩”——它仍然是惯用的Haskell,是自然合成的,是全面掌握Haskell技能的关键。只要你所做的I/O类型简单,它自然合成(这是一个需要努力的目标)。但如果事情变得复杂,例如更新文件而不是从一个文件读取和写入另一个文件,“自然”的组合将出现可怕的错误。请注意,懒惰的IO可能会导致许多难以调试和解决的问题。请参阅
lazyDoIO :: IO a -> IO [a]
lazyDoIO act = unsafeInterleaveIO $ do
    now <- act
    rest <- lazyDoIO act
    return (now : rest)

getText = lazyDoIO getChar
getText = unsafeInterleaveIO $ do
    c <- getChar
    s <- getText
    return (c : s)
getText = do
    c <- getChar
    if (c == '\n')
       then return [c]
       else do
              s <- getText
              return (c : s)

main = do
    s <- getText
    putStr s