太急于推断ocaml可选函数参数

时间:2017-05-11 14:35:35

标签: ocaml

考虑以下代码:

let myFun
  ?(f: ('a -> int) = (fun x -> x))
  (x: 'a)
    : int =
  f x

看起来我无法使用int以外的其他参数调用。当我尝试使用此代码时:

let usage = myFun ~f:String.length "abcdef"

Ocaml会发出以下错误消息:

Error: This expression has type string -> int
       but an expression was expected of type int -> int
       Type string is not compatible with type int 

由于默认参数,推理看起来会认为是'a = int。这是语言的限制,还是有一种方法可以编写它以便编译?

1 个答案:

答案 0 :(得分:5)

由于如何实施optionals参数,此问题是一个限制。

基本上,使用标准选项类型在类型检查阶段扩展带有可选参数的函数。例如,你的功能:

let f ?(conv=(fun x -> x)) x = f x

或多或少地变得

let f opt_conv =
let conv =
  match opt_conv with
  | None -> fun x -> x
  | Some f -> f in
 fun x -> conv x

因此,由于opt_conv'a->'a分支中的None类型有效,因此f必须为?conv:('a->'a) -> 'a -> 'a类型。

查看扩展函数,问题来自Some分支和None应具有不同类型以获得所需功能的事实。

为了类型谜语,在模式匹配的不同分支中具有不同类型是GADT可能带来潜在解决方案的标志:可以将扩展选项类型定义为

type ('default,'generic) optional =
  | Default: ('default,'default) optional
  | Custom: 'a -> ('default,'a) optional

然后可以将您的功能重写为

let f: type a. (int -> int, a -> int) optional -> a -> int =
fun conv x ->
  match conv with
  | Default -> x
  | Custom f -> f x

导致预期的行为:

f Default "hi"会产生类型错误,而f (Custom int_of_string) "2"会返回2.

但是,如果没有可选的参数语法糖机制,这实际上并没有用。

无论如何完全可以扩展OCaml以使用GADT-laded optional类型。然而,这很容易导致类型错误,相应的复杂性增加并不会带来非常有吸引力的扩展。