IO monad

沒有辦法從 IO a 型別的表示式中獲取 a 型別的值,並且不應該存在。這實際上是 monad 用於模擬 IO 的很大一部分原因。

IO a 型別的表示式可以被認為是表示可以與現實世界互動的動作,並且如果被執行,將導致 a 型別的某些東西。例如,前奏中的函式 getLine::IO String 並不意味著在 getLine 下面有一些我可以提取的特定字串 - 這意味著 getLine 表示從標準輸入獲取一行的動作。

毫不奇怪,main::IO (),因為 Haskell 程式確實代表了與現實世界互動的計算/動作。

可以IO a 型別的表示式做些什麼,因為 IO 是一個 monad:

  • 使用 (>>) 對兩個動作進行排序,以生成執行第一個動作的新動作,丟棄它產生的任何值,然後執行第二個動作。

      -- print the lines "Hello" then "World" to stdout
      putStrLn "Hello" >> putStrLn "World"
    
  • 有時你不想丟棄在第一個動作中產生的值 - 你真的希望它被送入第二個動作。為此,我們有了 >>=。對於 IO,它的型別為 (>>=) :: IO a -> (a -> IO b) -> IO b

     -- get a line from stdin and print it back out
     getLine >>= putStrLn
    
  • 取一個正常值並將其轉換為一個動作,它立即返回你給它的值。在你開始使用 do 表示法之前,此功能不太明顯有用。

     -- make an action that just returns 5
     return 5
    

更多來自 Haskell 的維基上的 IO 單子這裡