类型'a->'b的ML函数


19

我们的教授要求我们考虑OCaml中具有以下类型的函数

'a -> 'b

即,一个参数的函数可以是任何东西,并且可以返回不同的任何东西。

我想到了raise在忽略其参数的函数中使用:

let f x = raise Exit

但是这位教授说,有一种解决方案不需要标准库中的任何功能。我很困惑:'b如果一开始就没有一个,怎么办?

我在这里而不是在Stack Overflow上问是因为我想了解发生了什么,我不想只看一个没有解释的程序。


2
请针对您的答案中的CS101学生学习程序,而不是针对您的答案可能会激发他后来成为类型理论家。
吉尔(Gilles)'“ SO-不要邪恶”

如果您解释了自己发现raise的解决方案会有所帮助,那么我们知道如何最好地解释您的教授正在寻找的解决方案(其工作raise原理与工作原理相同)的原因。
sepp2k 2012年

@ sepp2k,raise : exn -> 'a所以我可以获得返回值,我只是忽略了该参数。
吉尔(Gilles)'“ SO-别邪恶”,2012年


Answers:


18

骨架是let f x = BODY。在BODY中,必须仅以通用方式使用x(例如,不要将其发送给需要整数的函数),并且必须返回任何其他类型的值。但是,后一部分又如何呢?为满足声明的唯一途径“为所有类型'b的返回值的类型的值'b”是为了确保功能并没有返回。确实有两种可能性:BODY错误或它没有终止。该函数raise故障,以下项不会终止:

let rec f x = f x

19

首先,一些评论。仅使用核心类型的lambda演算是不可能获得的,'a -> 'b因为键入系统(通过Curry Howard同构)与直觉逻辑相对应,并且相应的公式A → B也不是重言式。

其他扩展(例如元组和匹配/条件)仍然保留了一些逻辑一致性,添加*了与逻辑连接词and|相对应的乘积类型以及与or对应的求和类型。再次,不要指望他们会产生这种'a -> 'b类型,因为这将允许人们证明某种不是重言式的公式。

因此,您唯一的机会就是使用其他结构,这些结构会避开类似的逻辑raise(但在这种情况下您是不允许的)……或let rec!递归允许构建永远不会终止的程序,并且它们的结果可以赋予任意的返回类型,因为它们永远不会产生。现在,如果您考虑最琐碎的非终止函数(直接调用自身以返回结果的函数):

let rec f x = f x

您会注意到它的类型完全是'a -> 'b:无论提供什么参数,都可以假定结果(永远不会被计算)具有任何类型。

当然,这f不是一个有趣的功能,但这就是重点。在OCaml中,其类型看起来不像是有效公式的任何函数都是可疑函数。


询问者不理解您的前两段的内容,但我喜欢您的句子“它们的结果可以被赋予任意的返回类型,因为它们将永远不会产生”。
吉尔斯(Gilles)'所以

1

使用编译器原语,您​​可以编写以下代码:

external magic: 'a -> 'b = "%identity"

(虽然这不是语言的一部分,但确实由编译器发行版提供了此功能)。这是不安全的身份转换。

您的教授几乎肯定不想要这个。但是,这也是我所知道的唯一有用的类型函数'a -> 'b,并且确实在OCaml发行版中使用了它。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.