如何强制OCaml推断更一般的类型?
我想定义一个接受可选参数的函数,该参数是一个函数('a->'b)。默认值应该是identity,它实际上是如何强制OCaml推断更一般的类型?,ocaml,Ocaml,我想定义一个接受可选参数的函数,该参数是一个函数('a->'b)。默认值应该是identity,它实际上是('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。我能
('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\u apply
没有明确的类型?如果是这样,我如何获得类似的功能?这与常规类型('a->'b)
不兼容,原因如下:
- 第一个模式,
的类型为None->i+4
,因此将函数的返回类型限制为int
int
- 第二种模式,
也必须是somefn->fn(i+4)
类型。因为int
也是(i+4)
类型,int
必须获取并返回fn
,因此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)
在这里,typechecker只允许我们为f
使用一种类型:int->int
。如果它允许我们使用int->'a
类型,那么None
表达式的路径将是不健全的。换句话说,根据f
是None
还是Some
的不同,可选应用将对不同类型进行评估。这被认为是不合理的
证明不健全的最佳方法是给出一个简单的示例,其中typechecker将允许不健全的程序:
let f = ref None
let g n = optional_apply ?f:!f n
使用此定义,如果类型检查器允许f
参数保持多态性,那么我们可以随时通过更改f
引用来“中断”g
函数 我同意你的解释。很难理解为什么会这样。使用非可选参数f
而不是?f
,函数只是一个普通的apply
,保持f
的类型为常规类型没有问题apply
是多态的,可以与不同类型的f
一起重复使用,没有问题。好的,因此考虑可选参数的方法是定义函数时固定的option
类型。我错误地想象了一个类似于懒惰的打字构造的东西,它在需要时才被发现。但在Ocaml的背景下,这可能是胡说八道。