我在安装了 Jane street Base 库的 utop 中执行了以下命令
open Base;;
List.fold;;
打印出来了
- : 'a list -> init:'accum -> f:('accum -> 'a -> 'accum) -> 'accum = <fun>
我将其解释为折叠函数的第一个参数是值列表。第二个是初始值,第三个是折叠函数。文件夹函数,其第一个参数是累加器,第二个参数是正在折叠的列表中的项目。
根据这种解释,我编写了这段代码
List.fold [Some 1; None; None; Some 2] 0 (fun accm x -> match x with | None -> accum | Some x -> accum + x)
这不起作用,它会在屏幕上打印一些奇怪的东西
- : init:(int -> (int -> int option -> int) -> '_weak2) ->
f:((int -> (int -> int option -> int) -> '_weak2) ->
int option -> int -> (int -> int option -> int) -> '_weak2) ->
'_weak2
= <fun>
现在如果我更改 utop 中的代码以使用命名参数
List.fold [Some 1; None; Some 2] ~init:0 ~f:(fun accum x -> match x with | None -> accum | Some x -> accum + x);;
现在可以了。这是怎么回事?我按照记录签名建议的相同顺序传递参数?那为什么我被迫使用命名参数?
参数标签只能在明确的完整应用程序中省略。
特别是,对于具有多态返回类型(如
fold
)的标记函数来说,情况绝不会如此。事实上,对于这样的函数,没有明确的full application
概念。
例如,如果您查看您的初始申请:
List.fold [Some 1; None; None; Some 2] 0
(fun accm x -> match x with | None -> accum | Some x -> accum + x)
可以将其完成为以下完整应用程序:
List.fold
[Some 1; None; None; Some 2] 0
(fun acc x -> match x with None -> acc | Some x -> acc + x)
~init:(fun x f -> f x None)
~f:(fun f _ -> f )
因此,你的初始代码
List.fold [Some 1; None; None; Some 2] 0
(fun accm x -> match x with | None -> accum | Some x -> accum + x)
不是完整的应用程序,而是有效的部分应用程序,其中标记的参数仍然丢失。
我猜您正在使用 Jane Street 基础图书馆。因此,让我们从这些文档的链接开始。。
List.fold
确实接受初始化值和作为命名参数运行的函数。您尚未在以下位置提供这些命名参数:
List.fold [Some 1; None; None; Some 2] 0 (fun accm x -> match x with | None -> accum | Some x -> accum + x)
如果您尝试部分申请:
List.fold [Some 1; None; None; Some 2]
你会看到:
- : init:'_weak2 -> f:('_weak2 -> int option -> '_weak2) -> '_weak2 = <fun>
这是一个具有许多弱多态类型的新函数。 Jeffrey 在 Stack Overflow 上特别就这个主题撰写了大量文章。一个例子:https://stackoverflow.com/a/25798225/15261315。
然后将其应用于值
0
,得到:
- : init:(int -> '_weak3) ->
f:((int -> '_weak3) -> int option -> int -> '_weak3) -> '_weak3
我们可以通过我们自己设计的一个简单函数来看到这一点:
utop # let f a ~b ~g = g a b;;
val f : 'a -> b:'b -> g:('a -> 'b -> 'c) -> 'c = <fun>
utop # f 5;;
- : b:'_weak4 -> g:(int -> '_weak4 -> '_weak5) -> '_weak5 = <fun>
utop # f 5 6;;
- : b:'_weak6 -> g:(int -> '_weak6 -> int -> '_weak7) -> '_weak7 = <fun>