这个OCaml签名是否可行?

时间:2014-11-23 03:19:47

标签: ocaml

签名的OCaml功能:

'a -> 'b

可能?

我认为有可能,但是,我不知道答案背后的基本逻辑,所以解释它会很棒:)

编辑:它无法递归循环

4 个答案:

答案 0 :(得分:8)

有几个“合法”的答案。一个是永远循环,你排除了:

let rec f x = f x

另一种方法是通过提出异常或终止程序来分歧:

let f x = exit 0

let f x = assert false

let f x = failwith "die"

答案 1 :(得分:0)

可以使用:

let rec x = fun y -> x y;;

我不确定它是如何起作用的。 我知道x会有类型:

`a -> `b

和y会有类型:

`a

所以x:`a->`b y:`a将有类型:

`b

问题在于它似乎进入了一个无限循环。

答案 2 :(得分:0)

Obj个模块,具有Obj.magic功能。您可以使用外部magic原语来引入%identity之类的函数,例如:

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

但是你必须明白,所有这些绕过了类型系统,应该根本使用。在不破坏类型系统的情况下,类型'a -> 'b的所有函数共享相同的属性 - 不返回:因此它们应该引发异常(或使用其他非本地退出)或根本不返回。

答案 3 :(得分:-1)

是的!有各种“琐碎”的方法(通过终止程序,抛出异常或永远循环),但这是一个非常重要的方法,直接来自标准库:

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

这里,external用于调用使用OCaml的C API的C函数。通常,字符串将是要调用的C函数的名称,但"%identity"是一个不生成代码但只返回其参数的编译器内在函数。这利用了OCaml只信任为外部函数提供的类型签名这一事实,因为它无法验证它们。

它是Obj模块的一部分,其中存在此​​类低级别操作,并且通常以其完全限定名称Obj.magic来表示。这是一个不安全的身份证明,如下所示:

        OCaml version 4.03.0+dev5-2014-10-15

# external magic: 'a -> 'b = "%identity";;
external magic : 'a -> 'b = "%identity"
# Printf.printf "%d\n" (magic 1);;
1
- : unit = ()
# (* Crash *) print_string (magic 1);;
[1]    4010 segmentation fault (core dumped)  ocaml

段错误是因为OCaml在运行时不维护类型信息。此强制转换是未选中 - 编译器/解释器只是接受你的话。最后一个示例尝试取消引用1的内部表示(由于标记位而为0x3)作为指向字符串的指针,以及段错误。

此功能有合法用途,但很少见。一组在PrintfScanf来源,直到采用基于GADT的解决方案。其他用途是在Coq生成的程序中(它具有更强大的类型系统,因此可以证明转换是安全的,即使OCaml不能)。 Obj模块中的其他函数有时用于修改cons单元以进行尾递归列表操作,以及避免在极其性能关键的代码中出现间接的黑客攻击。

作为非常良好的规则:如果您不完全确定应该使用Obj模块中的功能,或者不确定此类使用是否安全,不要。使用它们是导致堆损坏的好方法,这很难调试,并且安全漏洞可导致任意代码执行,从类似问题判断在C和C ++中可以被利用。

相关问题