如何强制 OCaml 推断更通用的类型?
how to force OCaml to infer a more general type?
我想定义一个接受可选参数的函数,该参数是一个函数 ('a -> 'b)。默认值应该是标识,实际上是 ('a -> 'a)
,但我看不出为什么它不应该与更通用的 ('a -> 'b)
兼容。当我尝试时:
let optional_apply ?f i =
match f with
| None -> i + 4
| Some fn -> fn (i + 4)
我总是得到窄型 ?f:(int -> int) -> int -> int
。但我想将 f 保持为 int -> 'b
。我能做些什么?或者这只是不合理的,因为 optional_apply
没有确定的类型?如果是这样,我将如何获得类似的功能?
这与通用类型不兼容('a -> 'b)
。原因如下:
第一个模式 None -> i + 4
是 int
类型,因此将函数的 return 类型限制为 int
.
第二个模式 Some fn -> fn (i + 4)
必须 也 是 int
类型。因为 (i + 4)
也是 int
类型,fn
也必须采用 return 和 int
,因此 int -> int
.
我能想到的最佳选择是 Haskell 的 maybe
函数,类型为 ('a -> 'b) -> 'b -> 'a option -> 'b
:
let maybe fn backup opt = match opt with
| Some v -> fn v
| None -> backup
;;
...您可能可以根据自己的用例进行调整。
不可能,f
参数一定不能是可选的。一个简单的解释是,可选参数只是一个语法糖。
因此,如果没有糖,您的函数可以重写为以下形式:
let optional_apply f n = match f with
| Some f -> f (n + 4)
| None -> (n + 4)
这里的类型检查器只允许我们为 f
使用一种类型:int -> int
。如果它允许我们使用 int -> 'a
类型,那么表达式的 None
路径将是不可靠的。换句话说,根据 f
是 None
还是 Some
,optional_apply
将评估为不同的类型。这被认为是不合理的。
证明不健全的最好方法是举一个简单的例子,typechecker 将允许不健全的程序:
let f = ref None
let g n = optional_apply ?f:!f n
有了这个定义,如果类型检查器允许 f
参数保持多态性,那么我们可以随时 "break" g
通过改变 f
对任何东西的引用来发挥作用别的。
我想定义一个接受可选参数的函数,该参数是一个函数 ('a -> 'b)。默认值应该是标识,实际上是 ('a -> 'a)
,但我看不出为什么它不应该与更通用的 ('a -> 'b)
兼容。当我尝试时:
let optional_apply ?f i =
match f with
| None -> i + 4
| Some fn -> fn (i + 4)
我总是得到窄型 ?f:(int -> int) -> int -> int
。但我想将 f 保持为 int -> 'b
。我能做些什么?或者这只是不合理的,因为 optional_apply
没有确定的类型?如果是这样,我将如何获得类似的功能?
这与通用类型不兼容('a -> 'b)
。原因如下:
第一个模式
None -> i + 4
是int
类型,因此将函数的 return 类型限制为int
.第二个模式
Some fn -> fn (i + 4)
必须 也 是int
类型。因为(i + 4)
也是int
类型,fn
也必须采用 return 和int
,因此int -> int
.
我能想到的最佳选择是 Haskell 的 maybe
函数,类型为 ('a -> 'b) -> 'b -> 'a option -> 'b
:
let maybe fn backup opt = match opt with
| Some v -> fn v
| None -> backup
;;
...您可能可以根据自己的用例进行调整。
不可能,f
参数一定不能是可选的。一个简单的解释是,可选参数只是一个语法糖。
因此,如果没有糖,您的函数可以重写为以下形式:
let optional_apply f n = match f with
| Some f -> f (n + 4)
| None -> (n + 4)
这里的类型检查器只允许我们为 f
使用一种类型:int -> int
。如果它允许我们使用 int -> 'a
类型,那么表达式的 None
路径将是不可靠的。换句话说,根据 f
是 None
还是 Some
,optional_apply
将评估为不同的类型。这被认为是不合理的。
证明不健全的最好方法是举一个简单的例子,typechecker 将允许不健全的程序:
let f = ref None
let g n = optional_apply ?f:!f n
有了这个定义,如果类型检查器允许 f
参数保持多态性,那么我们可以随时 "break" g
通过改变 f
对任何东西的引用来发挥作用别的。