从 IO 中获取一个

一个常见的问题是“我有一个 IO a 的值,但我想对 a 值做一些事情:我如何获得它?” 如何对来自外部世界的数据进行操作(例如,递增用户键入的数字)?

关键是如果你对不纯粹获得的数据使用纯函数,那么结果仍然不纯。这取决于用户做了什么! IO a 类型的值代表“产生类型 a 的值的副作用计算”,它只能通过(a)将其组合成 main 和(b)编译和执行程序来运行。出于这个原因,在纯粹的 Haskell 世界中没有办法“将 a 取出”。

相反,我们想要构建一个新的计算,一个新的 IO 值,它在运行时使用 a 值。这是组成 IO 值的另一种方式,所以我们再次使用 do-notation:

-- assuming
myComputation::IO Int

getMessage::Int -> String
getMessage int = "My computation resulted in: " ++ show int
 
newComputation::IO ()
newComputation = do
  int <- myComputation       -- we "bind" the result of myComputation to a name, 'int'
  putStrLn $ getMessage int   -- 'int' holds a value of type Int

在这里,我们使用纯函数(getMessage)将 Int 转换为 String,但我们正在使用 do 表示法将其应用于计算运行 (之后)的计算结果。结果是更大的 IO 计算,newComputation。这种在不纯的上下文中使用纯函数的技术称为提升