ocaml 折叠参数顺序

问题描述 投票:0回答:2

我在安装了 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);;

现在可以了。这是怎么回事?我按照记录签名建议的相同顺序传递参数?那为什么我被迫使用命名参数?

ocaml
2个回答
3
投票

参数标签只能在明确的完整应用程序中省略。

特别是,对于具有多态返回类型(如

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)

不是完整的应用程序,而是有效的部分应用程序,其中标记的参数仍然丢失。


2
投票

我猜您正在使用 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>
© www.soinside.com 2019 - 2024. All rights reserved.