我想定义一个接受可选参数的函数,该函数是一个函数(' 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
不会有明确的类型?如果是这样,我将如何获得类似的功能?
答案 0 :(得分:3)
不可能,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
,optional_apply
会评估为不同的类型。这被认为是不健全的。
证明不健全的最好方法是给出一个简单的例子,其中typechecker将允许不健全的程序:
let f = ref None
let g n = optional_apply ?f:!f n
有了这个定义,如果类型检查器允许f
参数保持多态,那么我们可以在任何时候" break" g
通过将f
引用更改为其他任何内容来发挥作用。
答案 1 :(得分:2)
这与一般类型('a -> 'b)
不兼容。这就是原因:
第一种模式None -> i + 4
的类型为int
,因此将函数的返回类型限制为int
。
第二种模式Some fn -> 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
;;
...你可以适应你的用例。