OCaml中的多态递归:返回值

时间:2013-03-30 22:29:56

标签: recursion ocaml polymorphism

继续我关于类型级算术的一系列问题,我偶然发现了另一个问题:返回多态递归函数的类型。

这是代码:

module Nat : sig
  type z = Z
  type 'n s = S of 'n

  type ('n) nat =
          Zero : (z) nat
        | Succ : ('n) nat -> ('n s) nat

  val of_int : int -> 'n nat
end = struct
  type z = Z
  type 'n s = S of 'n
  type ( 'n) nat =
          Zero : ( z) nat
        | Succ : ('n) nat -> ('n s) nat

  let rec of_int n : int -> 'n nat = function
        0 -> Zero
        | n -> Succ (of_int (n - 1))
end

编制产量:

Error: This expression [Succ (of_int (n - 1))] has type 'a s nat
   but an expression was expected of type z nat

问题是在第一个模式匹配子句中,函数的返回值被设置为z nat by Zero。相反它应该是'a。 '一个nat?当尝试创建一个添加两个不同的Nat:s的函数时,也会出现此问题。

感谢你的帮助。

1 个答案:

答案 0 :(得分:4)

类型int -> 'n nat,表示forall n, int -> n nat:该函数的用户可以选择n使用该函数。所以你可以打电话给of_int函数说“嘿,这次给我一个(z s) nat”,就像你可以选择最终的[] : 'a list类型一样。这与实际发生的情况不匹配,即你不选择类型,它由整数的值决定。

根据定义,类型系统不知道整数的值,因此您无法准确地说出结果会得到哪种类型n nat。您可以说,存在某种类型n,例如结果类型为n nat。您可以使用“存在类型”来表达,并且有多种方法可以做到这一点,GADT就是其中之一(GADT是代数数据类型加上存在类型和等式约束)。

type some_nat =
| Some : 'n nat -> some_nat

let rec of_int = function
| 0 -> Some Zero
| n ->
  let (Some nat) = of_int (n - 1) in
  Some (Succ nat)

some_nat是围绕nat的存在主义,如果你有一流的存在类型,它等同于你可能写的exists n. n nat

处理添加更加困难,因为你必须在类型级别表达你得到的类型实际上对应于另外两种类型的添加。以下是我为它定义类型的方法:

type (_, _, _) add =
| AddZ : (z, 'b, 'b) add
| AddS : ('a, 'b, 'c) add -> ('a s, 'b, 'c s) add

type ('a, 'b) add_result =
| Result : ('a, 'b, 'c) add * 'c nat -> ('a, 'b) add_result

let rec add : type a b . a nat -> b nat -> (a, b) add_result = function
   ...

我会让你定义add的正文,这样你就可以自己玩这些东西了。

我对add类型的所有运行时换行(对于类型级证人来说真的很有用)感到高兴,所以也许有更好的方法。