簡體   English   中英

為什么Haskell沒有I Monad(僅用於輸入,與IO monad不同)?

[英]Why does Haskell not have an I Monad (for input only, unlike the IO monad)?

從概念上講,執行輸出的計算似乎與僅執行輸入的計算非常不同。 從某種意義上說,后者更為純粹。

舉個例子,我希望有一種方法可以將我的程序中僅輸入的部分與可能實際寫出的部分分開。

那么,為什么只有Monad沒有輸入?

任何原因導致I monad(以及可以合並到IO Monad中的O Monad)的任何原因?

編輯 :我主要是指輸入為閱讀文件,而不是與用戶交互。 這也是我的用例,我可以假設輸入文件在程序執行期間不會改變(否則,可以獲得未定義的行為)。

我不同意bdonlan的回答。 確實,輸入和輸出都不是更“純粹”,但它們完全不同的。 將IO視為單個“罪孽箱”並將所有效果擠在一起是非常有效的,它確實可以確保某些屬性更難。 例如,如果您知道許多函數只從某些內存位置讀取,並且永遠不會導致這些位置被更改,那么很高興知道您可以重新排序它們的執行。 或者如果你有一個使用forkIO和MVars的程序,那么根據它的類型知道它也不是在讀取/ etc / passwd會很高興。

此外,除了堆疊的變壓器之外, 還可以以一種方式構成單子效應。 你不能用所有的 monad(只是免費的monad)來做這件事,但對於這樣的情況,你真正需要的只是。 例如,iospec軟件包提供了純粹的IO規范 - 它沒有單獨的讀寫,但它確實將它們分開,例如STM,MVars,forkIO,soforth。

http://hackage.haskell.org/package/IOSpec

關於如何干凈地組合不同monad的關鍵想法在“ 數據類型單點紙”(很好的閱讀,非常有影響力,不能推薦,等等)中有所描述。

IO monad的“輸入”側輸出與輸入一樣多。 如果您消耗了一行輸入, 那么您消耗該輸入事實將傳達給外部,並且還可以記錄為不純的狀態(即,您之后不會再次使用相同的行); 它與putStrLn一樣多的輸出操作。 此外,必須根據輸出操作對輸入操作進行排序; 這又限制了你可以將兩者分開的程度。

如果你想要一個純粹的只讀monad,你應該使用reader monad

也就是說,你似乎對組合monad可以做什么有點困惑。 雖然你確實可以組合兩個monad(假設一個是monad變換器)並獲得某種混合語義,但你必須能夠運行結果 也就是說,即使您可以定義IT (OT Identity) r ,您如何運行它? 在這種情況下,您沒有root IO monad,因此main必須是純函數。 這意味着你有main = runIdentity . runOT . runIT $ ... main = runIdentity . runOT . runIT $ ... main = runIdentity . runOT . runIT $ ... 這是無稽之談,因為你從純粹的語境中獲得了不純凈的效果。

換句話說,IO monad的類型必須是固定的。 它不能是用戶可選擇的轉換類型,因為它的類型被固定為main 當然,你可以稱之為 I (O Identity) ,但你沒有獲得任何東西; O (I Identity)將是一個無用的類型,就像I []O Maybe ,因為你永遠無法運行任何這些。

當然,如果將IO保留為基本IO monad類型,則可以定義以下例程:

runI :: I Identity r -> IO r

這很有效,但同樣,你不能輕易地擁有這個我monad下面的任何東西,而且你並沒有從這種復雜性中獲得太多。 無論如何,將一個輸出monad轉換為List基本monad甚至意味着什么呢?

當您獲得輸入時,會導致副作用改變外部世界的狀態(消耗輸入)和程序(使用輸入)。 輸出時,會產生只會改變外界狀態的副作用(產生輸出); 輸出本身的行為不會改變程序的狀態。 所以你可能會說OI更“純粹”。

除了輸出確實改變了程序的執行狀態 (它不會一遍又一遍地重復相同的輸出操作;它必須進行某種狀態改變才能繼續)。 這一切都取決於你如何看待它。 但是將輸入和輸出的骯臟程度混淆到同一個monad中要容易得多。 任何有用的程序都將輸入和輸出。 您可以將您使用的操作分類為一個或另一個,但我沒有看到使用類型系統執行任務的令人信服的理由。

要么你正在搞亂外面的世界,要么你不是。

簡短回答:IO不是I / O. 如果你願意,其他人有更長的答案。

我認為純代碼和不純代碼之間的區別有點武斷。 這取決於你放置屏障的位置。 Haskell的設計師決定將語言的純功能部分與其他部分明確區分開來。

所以我們有IO monad,它包含了所有可能的效果(不同的,如磁盤讀/寫,網絡,內存訪問)。 語言通過返回類型強制執行明確的划分。 這引發了一種將純粹和不純潔的東西分開的思維方式。

如果涉及信息安全,將閱讀和寫作分開是很自然的。 但是對於haskell的最初目標,要成為一種標准的懶惰純函數語言,這是一種矯枉過正。

暫無
暫無

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

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