OCaml:具有多态变体的类型推断

时间:2015-04-26 13:29:24

标签: ocaml type-inference

函数f参数类型是[< 'A | 'B],这就是我想要的。

# let rec f = function
  | `A -> 0
  | `B -> let _ = f in 1
;;
val f : [< `A | `B ] -> int = <fun> 

但是,如果我使用'A以递归方式调用它,则会向我推断出不需要的[< 'A | 'B > 'A]类型,至少需要'A

# let rec f = function
  | `A -> 0
  | `B -> let _ = f `A in 1
;;
val f : [< `A | `B > `A ] -> int = <fun>

我仍需要递归调用f 'A,但如何保留[< 'A | 'B]类型?

1 个答案:

答案 0 :(得分:2)

这是let - 多态约束的另一个实例,它阻碍了多态递归函数的使用。因为,OCaml 3.12我们有一个explicit way来声明你的函数是多态的。

你的情况有点复杂,因为你有隐式类型变量,它发生在row-polymorphic类型中。也许有更好的方法,但我的方法是使这个类型变量显式化,具有以下类型定义

type 'a t = 'a constraint 'a = [< `A | `B]

使用这种方便的类型,很容易为函数编写适当的注释:

let rec f : 'a . 'a t -> int = function
| `A -> 0
| `B -> let _ = f `A  in 1

以防万一,如果您不想公开此'a t,那没关系,因为您不需要,'a t等于{{ 1}}它只是使[< 'A | 'B]类型变量显式:

'a

如果不引入module M : sig val f : [< `A | `B] -> int end = struct let rec f : 'a . 'a t -> int = function | `A -> 0 | `B -> let _ = f `A in 1 end;; 类型,你可以稍微用一点(但这当然是品味的话)来表示:

'a t

当然,对于非平凡的类型,这不会扩展。