簡體   English   中英

為什么我不能用seq強制執行IO操作?

[英]Why can't I force an IO action with seq?

鑒於此代碼段:

someFunction x = print x `seq` 1

main = do print (someFunction "test")

執行代碼時為什么不print x打印test

$./seq_test 
1

如果我用error替換它我可以檢查seq的左操作數是否確實被評估。

我怎樣才能達到預期的輸出:

test
1

只修改someFunction

評估IO操作不會做任何事情。 那就對了!

如果您願意, IO類型的值僅僅是“指令列表”。 因此,所有你與該做的seq是強制程序是,如果實際使用的動作做什么肯定1。 使用動作與評估無關,它意味着將其與main調用單獨綁定。 但是,正如你所說, someFunction是一個具有非someFunction簽名的函數 ,這在這里不可能發生。

你能做什么...... 但不要做

import Foreign

someFunction x = unsafePerformIO (print x) `seq` 1

這實際上將評估與IO執行相結合。 這通常在Haskell中是一個非常糟糕的主意,因為評估可能發生在完全不可預測的順序上,可能發生的次數可能比你想象的要多(因為編譯器假設參考透明度),以及其他混亂場景。

正確的解決方案是將簽名更改為monadic:

someFunction :: Int -> IO Int
someFunction x = do
     print x
     return 1

main = do
     y <- someFunction "test"
     print y

1事實上,即使沒有seq ,程序仍然盡可能確定。 只有通過執行操作才能獲得更多細節。

seq表達式計算為弱頭正常形式,這只是最外層的構造函數(或lambda應用程序)。 表達式print x已經在WHNF中,因此seq不做任何事情。

您可以使用Debug.Trace.trace函數獲得您正在尋找的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM