gpt4 book ai didi

function - 什么时候可以调用带有标签参数而不带标签的函数?

转载 作者:行者123 更新时间:2023-12-01 22:01:21 25 4
gpt4 key购买 nike

似乎在某些情况下,如果顺序正确,您可以调用带标签参数的函数,而无需标签;例如

let f ~x ~y = Format.sprintf "%d %s" x y;;
f 3 "test";;

运行成功,但是

f "test" 3;;

失败并显示错误消息

Line 1, characters 2-8:
Error: This expression has type string but an expression was expected of type
int

对于带有可选参数的函数,如果不传入可选参数,它似乎可以工作:

let f ?(x = 1) ~y () = Format.sprintf "%d %s" x y;;
f "help" ();;

成功了,但是

f 2 "help" ();;

失败并显示错误消息

Line 1, characters 4-10:
Error: The function applied to this argument has type
?x:int -> y:string -> string
This argument cannot be applied without label

是否有关于何时可以这样做的一般规则?

最佳答案

如果应用程序是完整的(即提供了所有必需的参数),并且如果函数的返回类型不是类型变量,则可以省略标签。可选参数的参数必须始终通过标签传递。

让我们举一些例子

let example1 ?(opt=0) ~a ~b ~c unlabeled = 
opt + a + b + c + unlabeled;;

example1 1 2 3 4;;
- : int = 10

在这里,我们能够应用所有没有标签的参数,因为我们已经提供了所有必需的参数(可选参数不是必需的,因此得名),并且结果类型不是多态的。但是,如果我们从 Core 或 ListLabels 中获取具有类型的 List.fold 函数

'a list -> init:'accum -> f:('accum -> 'a -> 'accum) -> 'accum

然后我们会得到,

List.fold [1;2;3;4] 0 (+);;
- : init:(int -> (int -> int -> int) -> '_weak1) ->
f:((int -> (int -> int -> int) -> '_weak1) ->
int -> int -> (int -> int -> int) -> '_weak1) ->
'_weak1

而不是人们所期望的10。原因是由于结果类型 'accum 是一个类型变量,因此它也可以是一个函数,例如 int -> intstring -> int -> unit 等——所有这些类型都与 'accum 类型匹配。这基本上意味着该函数接受可能无限数量的位置参数。因此,我们提供的所有参数都被解释为位置参数,因此,我们永远无法填写标记的参数,因此,我们的应用程序并不是完整的。这实际上使我们在发布开始时对规则的原始定义变得多余 - 因为用类型变量表示类型的应用程序永远不可能是完整的。

请注意,这个问题仅在返回类型为类型变量时出现,而不仅仅是包含某些类型变量,例如,我们可以使用 List.map 函数轻松省略标签,例如,给定来自 Core 的 List.map,其类型为

'a list -> f:('a -> 'b) -> 'b list

我们可以轻松应用它

# List.map [1;2;3] ident;;
- : int Core_kernel.List.t = [1; 2; 3]

尽管如此,通常认为省略标签是一种不好的做法。主要是因为多态返回类型的警告,并且因为它使得标记参数的顺序很重要,这有点违反直觉。

关于function - 什么时候可以调用带有标签参数而不带标签的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58315641/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com