作爲一篇序言,它不是「IO
Monad
」,儘管很多寫得不好的介紹說。這只是「IO
類型」。單子沒有什麼神奇的。 Haskell的Monad
類是一個非常無聊的事情 - 它只是大多數語言可以支持的不熟悉和抽象。你永遠不會看到任何人打電話IO
「IO
Alternative
」,即使IO
實施Alternative
。專注於Monad
只會妨礙學習。
在純語言中原則上處理效果(而不是副作用!)的概念魔術根本就存在IO
類型。這是一個真正的類型。這不是一個國旗說「這是不純的!」。它是一個完整的Haskell類型* -> *
,就像Maybe
或[]
一樣。將類型簽名接受IO值作爲參數,如IO a -> IO (Maybe a)
,這是合理的。使用嵌套的IO輸入簽名很有意義,如IO (IO a)
。
所以如果它是一個真正的類型,它必須有一個具體的含義。作爲類型的Maybe a
表示類型a
的可能缺失值。 [a]
表示類型爲a
的0個或更多值。 IO a
表示產生a
類型值的一系列效果。
請注意,IO
的整個目的是表示一系列效果。正如我上面所說,他們不是副作用。它們不能隱藏在程序的無傷大雅的葉子中,神祕地改變其他代碼背後的東西。相反,由於它們是IO
值,所以效果被明確地調出。這就是爲什麼人們試圖使用IO
類型來最小化他們的程序的一部分。你在那裏做的越少,在遠處干擾你的程序的怪異行爲的方式越少。
至於你的問題的主要推力,那麼 - 一個完整的Haskell程序是一個IO
的值,main
,以及它使用的定義集合。編譯器在生成代碼時,插入一個確實非Haskell代碼塊,該代碼塊實際運行IO
值中的效果序列。從某種意義上說,這就是Simon Peyton Jones(GHC的長期作者之一)在他的演講Haskell is useless中所做的。
的確,無論實際執行IO操作如何,都不能保持概念上的純粹。(這裏有一個非常不純的函數,運行在Haskell語言中暴露的動作IO
。我不會再多說它,它會被添加來支持外部函數接口,並且不恰當地使用它會使程序非常糟糕。)但是Haskell的重點是爲效果系統提供一個原則性的接口,並隱藏無原則的位。而且它在實踐中確實非常有用。
(評論,因爲我不是100%確定這一點)我的理解是,IO被模擬爲一個低級別的狀態monad與「現實世界」作爲國家。編譯器/運行庫實際上將其轉換爲使用綁定到操作系統的API實現的IO操作。一個純粹的函數式編程能夠計算出任何東西,但不會告訴任何人。我們需要一個運行時,可以將現實世界中的這些有狀態操作轉換爲對底層操作系統的實際調用。 – bheklilr
https://wiki.haskell.org/IO_inside#Welcome_to_the_RealWorld.2C_baby –