IO与参考透明度

Ron*_*Ron 2 haskell referential-transparency

对不起,这里有一个新问题,但Haskell如何知道不会将引用透明度应用于例如readLnputStrLn两次相同的字符串?是因为IO参与了吗?IOW,编译器不会将引用透明度应用于返回的函数IO吗?

Mat*_*hid 11

您需要区分评估执行.

如果计算 2 + 7,则结果为9.如果将一个计算结果为9的表达式替换为另一个表达式,该表达式也计算为9,则程序的含义未更改.这是参考透明度保证的.我们可以共享几个减少到9的共享表达式,或者将共享表达式复制到多个副本中,并且程序的含义不会改变.(性能可能,但不是最终结果.)

如果进行评估 readLn,则计算结果为I/O命令对象.您可以将其想象为描述您想要执行的I/O操作的数据结构.但对象本身就是数据.如果计算readLn两次,它将返回相同的I/O命令对象两次.您可以将多个副本合并为一个副本; 你可以将一个副本分成几个.它不会改变程序的含义.

现在,如果您想执行 I/O操作,那就是另一回事了.显然,I/O操作需要以程序指定的方式执行,而不是随机复制或重新排列.但这没关系,因为不是Haskell表达式评估引擎就是这样做的.您可以假装Haskell运行时运行main,它构建一个代表整个程序的巨大I/O命令对象.然后,Haskell运行时读取此数据结构并按指定的顺序执行它请求的I/O操作.(实际上它不是如何工作的,而是一种有用的心理模型.)

通常,您不需要考虑在评估 readLn获取I/O命令对象然后执行生成的I/O命令对象以获得结果之间的这种严格分离.但严格来说,这是理所当然的.

(您可能也听说I/O"形成一个monad".这只是一种奇特的方式,说有一组特定的操作符可以将I/O命令对象一起更改为更大的I/O命令对象.它不是理解评估和执行之间的分离.)