我试图将引用透明度的定义与OCaml如何处理多态类型和副作用相协调。我在 https://web.archive.org/web/20120729232358/http://www.csc.villanova.edu/~dmatusze/resources/ocaml/ocaml.html 上读到了这一点
如果定义的含义不依赖于其所处的上下文,则称其具有参考透明度。OCaml 中的函数具有引用透明度,也就是说,更改上下文(其他变量和其他函数)不会更改已定义的任何函数的含义。在调试程序时,这一事实可能至关重要,因为您可能会相当频繁地重新定义函数。
但是我的理解方式,这在OCaml中是不正确的,因为在返回输入函数的任何内容之前,可以执行一大堆副作用(如写入文件和执行其他计算)。
您可能有一个函数f : string -> string
,以便f "a"
不等于f "a"
。 我们可以将一些副作用表达式放入函数的主体中,这些表达式在 f
的类型描述中完全不可见
例如,可以定义f
返回某个文件的第一行。 在f
上下文中的某个地方可能有一个函数被更改,它会影响f
返回的第一行。 或者更糟糕的是,上下文中的某些函数可能会删除f
依赖的文件,这将使f
未定义。
那么OCaml是参考透明的还是我错过了什么?
Ocaml 在引用上不是透明的,正如你所解释的那样。
也许Matuszek想强调Ocaml的功能方面,但在我看来,他是误导性的,或者完全是错误的。
例如,部分表达式(但不是语句)说OCaml is a purely functional language
和OCaml claims to be stateless
。节遗漏说
循环也被省略了,但无论如何,它们在纯函数式语言中并不是很有用。
这很有趣,因为如果循环没有用,它们就不会添加到 Ocaml 中。
引用透明意味着函数的上下文不会影响结果,而"纯"函数是仅依赖于其参数且没有副作用的函数。例如在
# let y = 10;;
# let f x = (Printf.printf "%d+%d=%dn" x y (x+y); x+y);;
val f : int -> int = <fun>
# f 5;;
5+10=15
- : int = 15
# let y = 3;;
val y : int = 3
# f 5;;
5+10=15
- : int = 15
我们看到 f 在引用上是透明的(因为当你重新定义 y 时它不会改变)但不纯。