我在Haskell中练习一些练习,探索一些我不熟悉的地方,但我一直无法理解我在混合System.Timeout
和System.IO.Unsafe
时得到的行为。超时和unsafePerformIO
我懒读一个流,getContents
,用纯函数过滤它,并输出结果。一个典型的过滤器会是这样:
import Data.List(break)
import System.Timeout(timeout)
import System.IO.Unsafe(unsafePerformIO)
main = do
text <- getContents
putStr $ aFilter text
aFilter text = h ++ t where
(h, t) = getUntil "\n" text
getUntil separator text = break (\x -> (separator!!0) == x) text
而且有了这样的过滤器,程序读取所有标准输入,符合市场预期,并输出到标准输出。但如果我这样做:
aFilter text = result where
l = consumeWithTimeout (getUntil "\n" text)
result = case l of
Nothing -> "Timeout!\n"
Just (h, t) -> h ++ t
consumeWithTimeout (x, y) = unsafePerformIO $! timeout 6 $! deepseq x (return (x, y))
我希望我的程序立即超时,打印“超时!”消息,并关闭。相反,它挂在那里,等待输入。
我错在认为timeout
函数在程序启动时被评估过吗?我期待它,因为我立即将其部分返回值写入stdout,并且每次输入一行时,软件都会做出反应。是unsafePerformIO
插入某种懒惰到我的函数?或者它是否将懒惰插入System.Timeout
的内部?
1)如果您不得不询问'unsafePerformIO',那么您不应该使用'unsafePerformIO'。这个例子当然是一个误用。改用'spoon'库来代替。 2)这段代码不能编译。在将来的问题中,请张贴您实际使用的代码。 –
1)但是如果我不尝试在陌生的地方使用unsafePerformIO,我无法真正理解Haskell的评估规则。 2)抱歉没有编译,我完成了代码并纠正了错误。我尝试了几件不同的事情,并删除了一段帖子。 – marcosdumay
另外,增加了一个强制x的评估的深度。它不会改变结果。 – marcosdumay