为什么不能像 OCaml 中的常规函数​​一样传递数据构造函数?

Hav*_*ung 4 ocaml function

例如,考虑以下代码:

type foo = Foo of int

let apply z f = f z

(* This is not allowed *)
let create_foo = Foo

(* This is allowed *)
let create_foo i = Foo i

(* This is not allowed *)
apply 1 Foo

(* This is allowed *)
apply 1 create_foo
Run Code Online (Sandbox Code Playgroud)

数据构造函数是必须完全应用的特殊功能吗?当作为功能使用,Foocreate_foo在他们所做的事情是相同的。禁止将其Foo用作可以传递和部分应用的常规函数​​的原因是什么?

Haskell 似乎允许这种行为。

gle*_*nsl 7

从马的嘴里,Xavier Leroy,在这个 2001 年的邮件列表消息中

旧的 Caml V3.1 实现将构造函数视为类似于 SML 的函数。在 Caml Light 中,出于以下几个原因,我选择放弃这种等效性:

  • 编译器的简单性。在内部,构造函数不是函数,需要特殊情况将 Succ 转换为 (fun x -> Succ x)。这并不难,但请记住,Caml Light 确实是 Caml 的精简版。

  • Caml Light 和OCaml 中的构造函数确实有一个arity,例如C of int * int 实际上是一个带有两个整数参数的构造函数,而不是一个带有一个参数的构造函数,它是一对。因此,将有两种方法将构造函数 C 映射到函数: fun (x,y) -> C(x,y) 或 fun xy -> C(x,y) 如果您来自SML 背景(其中构造函数有 0 或 1 个参数),但后者更适合 Caml Light / OCaml 执行模型,它有利于柯里化函数。通过不像函数那样对待构造函数,我们避免了必须选择......

  • 代码清晰。虽然将构造函数用作函数有时很方便,但我认为它通常难以阅读。写“fun x -> Succ x”更冗长,但我认为更容易阅读。

  • 非常感谢,这是有道理的。在这个答案中添加一点[历史背景](https://en.wikipedia.org/wiki/Caml#History)(因为我必须搜索这个)。“[Caml 的]后继者 Caml Light 由 Xavier Leroy 和 Damien Doligez 用 C 语言实现,最初的版本由于其更高的内存和 CPU 要求而被昵称为“Heavy Caml”。Caml Special Light 是进一步完整的重写,增加了强大的功能模块系统到核心语言。它通过对象层进行了增强,成为 Objective Caml,最终更名为 OCaml。” (2认同)