我在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