OCaml:是否有类型'a - >的函数'除了身份功能?

时间:2010-10-15 18:26:37

标签: functional-programming types ocaml

顺便说一句,这不是一个功课问题。它在课堂上长大,但我的老师想不出来。感谢。

4 个答案:

答案 0 :(得分:19)

如何定义身份功能?如果您只考虑语法,则会有不同的标识函数,它们都具有正确的类型:

let f x = x
let f2 x = (fun y -> y) x
let f3 x = (fun y -> y) (fun y -> y) x
let f4 x = (fun y -> (fun y -> y) y) x
let f5 x = (fun y z -> z) x x
let f6 x = if false then x else x

甚至还有更奇怪的功能:

let f7 x = if Random.bool() then x else x
let f8 x = if Sys.argv < 5 then x else x

如果你将自己局限于OCaml的一个纯子集(它排除了f7和f8),你可以构建的所有函数都验证了一个观察方程式,从某种意义上说,它确保了它们计算的内容是身份:对于所有值f : 'a -> 'a,我们都有f x = x

该等式不依赖于特定函数,它由类型唯一确定。有几个定理(框架在不同的上下文中)形式化了非正式的观点,即“多态函数不能改变多态类型的参数,只传递它”。例如,参见Philip Wadler的论文,Theorems for free!

这些定理的好处在于它们不仅适用于'a -> 'a情况,这不是那么有趣。您可以从排序函数的('a -> 'a -> bool) -> 'a list -> 'a list类型中获取一个定理,该函数表示其应用程序与单调函数的映射进行通信。 更正式的是,如果您有任何具有此类型的函数s,那么对于所有类型u, v,函数cmp_u : u -> u -> boolcmp_v : v -> v -> boolf : u -> v和列表{ {1}},如果li : u list暗示cmp_u u u'(f是单调的),您有:

cmp_v (f u) (f u')

map f (s cmp_u li) = s cmp_v (map f li) 完全是一个排序函数时,确实如此,但我发现能够证明任何具有相同类型的函数s都是真的令人印象深刻。

一旦允许非终止,通过分散(无限循环,如上面给出的s函数),或者通过引发异常,当然你可以有任何东西:你可以构建一个类型为{的函数{1}},类型不再具有任何意义。使用let rec f x = f x具有相同的效果。

有一些更好的方法可以失去与身份的等同性:你可以在非空的环境中工作,可以从函数中访问预定义的值。例如考虑以下函数:

'a -> 'b

你仍然是所有x的属性,Obj.magic : 'a -> 'b:如果你只考虑返回值,你的函数仍然表现为身份。但是一旦你考虑了副作用,你就不再等同于(无副作用)身份:如果我知道let counter = ref 0 let f x = incr counter; x ,我可以编写一个分离函数,当给出这个时返回f x = x函数counter,并且对于纯身份函数将返回false。

true

如果隐藏计数器(例如通过模块签名,或简称为f),并且没有其他函数可以观察到它,那么我们再次无法区分let separate g = let before = !counter in g (); !counter = before + 1 和纯身份函数。因此,在当地政府面前,这个故事更为微妙。

答案 1 :(得分:13)

let rec f x = f (f x)

此函数永不终止,但它的类型为'a -> 'a

如果我们只允许全部功能,问题会变得更有趣。如果不使用邪恶的技巧,就不可能编写'a -> 'a类型的总函数,但邪恶的技巧很有趣:

let f (x:'a):'a = Obj.magic 42

Obj.magic'a -> 'b类型的邪恶憎恶,它允许所有类型的恶作剧绕过类型系统。

第二个想法是,一个不是全部,因为它与盒装类型一起使用时会崩溃。

所以真正的答案是:身份函数是'a -> 'a类型的唯一总函数。

答案 2 :(得分:9)

抛出异常也可以为您提供'a -> 'a类型:

# let f (x:'a) : 'a = raise (Failure "aaa");;
val f : 'a -> 'a = <fun>

答案 3 :(得分:2)

如果你将自己限制在一个“合理的”强正规化类型的λ演算中,那么就存在一个类型为∀αα→α的函数,它是同一性函数。您可以通过检查此类术语的可能正常形式来证明它。

菲利普·瓦德勒(Philip Wadler)1989年的文章"Theorems for Free"解释了具有多态类型的函数如何必然满足某些定理(例如类似地图的函数与组合通信)。

当处理多态性时,有一些非直观的问题。例如,通过使用其recursor函数表示归纳对象(例如列表),存在用于使用impredicative polymorphism编码归纳类型和递归的标准技巧。在某些情况下,有些属于recursor函数类型的术语不是recursor函数; Christine Paulin's PhD thesis的§4.3.1中有一个例子。