OCaml中的引用透明性

OCaml中的引用透明性,ocaml,side-effects,referential-transparency,Ocaml,Side Effects,Referential Transparency,我试图将引用透明性的定义与OCaml处理多态类型和副作用的方式相协调。我读到了 如果一个定义的含义不取决于它所处的上下文,那么它就被称为具有参考透明度。OCaml中的函数具有引用透明性,也就是说,更改上下文(其他变量和其他函数)不会更改您已经定义的任何函数的含义。这一事实在调试程序时非常重要,因为您可能会相当频繁地重新定义函数 但我的理解是,这在OCaml中不可能是真的,因为在返回输入函数的内容之前,可能会执行一系列副作用(比如写入文件和执行其他计算) 您可能有一个函数f:string->str

我试图将引用透明性的定义与OCaml处理多态类型和副作用的方式相协调。我读到了

如果一个定义的含义不取决于它所处的上下文,那么它就被称为具有参考透明度。OCaml中的函数具有引用透明性,也就是说,更改上下文(其他变量和其他函数)不会更改您已经定义的任何函数的含义。这一事实在调试程序时非常重要,因为您可能会相当频繁地重新定义函数

但我的理解是,这在OCaml中不可能是真的,因为在返回输入函数的内容之前,可能会执行一系列副作用(比如写入文件和执行其他计算)

您可能有一个函数
f:string->string
,这样
f“a”
就不等于
f“a”
。我们可以在函数体中插入一些在
f
的类型描述中完全不可见的副作用表达式

例如,
f
可以定义为返回某个文件的第一行。
f
上下文中的某个地方可能有一个函数发生了更改,这会影响第一行
f
返回的内容。更糟糕的是,上下文中的某些函数可能会删除
f
所依赖的文件,这将导致
f
未定义


那么OCaml是引用透明的还是我遗漏了什么呢?

正如您所解释的,OCaml不是引用透明的

也许Matuszek想强调Ocaml的功能方面,但在我看来,他是误导性的或完全错误的

例如,
OCaml是一种纯粹的函数式语言,
OCaml声称是无状态的。部分说

循环也被省略了,但它们在纯函数式语言中并不是非常有用


这很有趣,因为循环如果没有用处就不会被添加到Ocaml中。

引用透明意味着函数的上下文不会影响结果,而“纯”函数是一个只依赖于其参数且没有副作用的函数。例如在

# let y = 10;;
# let f x = (Printf.printf "%d+%d=%d\n" 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
#设y=10;;
#设fx=(Printf.Printf“%d+%d=%d\n”xy(x+y);x+y);;
val f:int->int=
#f5;;
5+10=15
-:int=15
#设y=3;;
val y:int=3
#f5;;
5+10=15
-:int=15

我们看到f是引用透明的(因为当你重新定义y时它不会改变),但是不纯净。

你是在问OCaml还是这些函数?您在这里描述的函数不是引用透明的,因为它们显然不是没有副作用的。我问的是OCaml,我认为副作用与引用透明性无关。纯函数的记忆版本通常使用哈希映射来存储以前计算的值,但函数本身仍然是引用透明的,即使修改哈希映射被认为是一种副作用。我认为
f
是引用不透明的,即不是引用透明的。Quoting:>这要求表达式是纯的,也就是说,对于相同的输入,表达式值必须相同,并且其计算必须没有副作用。将
f5
替换为
15
将通过消除打印副作用来更改程序。