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 单子这里