【问题标题】:Ocaml's named parametersOcaml 的命名参数
【发布时间】:2012-08-02 23:58:56
【问题描述】:

试图了解 Ocaml 的命名参数机制。我了解基础知识,但doc 显示了这样的示例:

# let f ~x ~y = x - y;;
val f : x:int -> y:int -> int = <fun>

# let x = 3 and y = 2 in f ~x ~y;;
- : int = 1

在应用程序中仅使用波浪号时究竟发生了什么?它只是~x:x 的简写,类似于定义吗?如果是这样,有人可以解释为什么会这样:

# ListLabels.fold_left;;
- : f:('a -> 'b -> 'a) -> init:'a -> 'b list -> 'a = <fun>

# let add = (+) and i = 0 
in ListLabels.fold_left ~add ~i [1;2;3];;

生产

- : f:((add:(int -> int -> int) -> i:int -> 'a) ->
   int -> add:(int -> int -> int) -> i:int -> 'a) ->
init:(add:(int -> int -> int) -> i:int -> 'a) -> 'a = <fun>

【问题讨论】:

    标签: ocaml currying named-parameters


    【解决方案1】:

    男人说 “请注意,结果类型为类型变量的 ListLabels.fold_left 等函数永远不会被视为完全应用。”

    这是您的示例中发生的情况。小心它有点牵扯。

    # ListLabels.fold_left;;
    - : f:('a -> 'b -> 'a) -> init:'a -> 'b list -> 'a = <fun>
    

    只是经典用法:ListLabels.fold_left 带有 3 个参数,即标记为 f 的函数、初始化器 init 和列表。

    现在,在

    let add = (+) and i = 0 
    in ListLabels.fold_left ~add ~i [1;2;3];;
    

    应用程序ListLabels.fold_left ~add ~i [1;2;3] 被认为是不完整的(正如该人所说)。这意味着`ListLabels.fold_left 首先接收其未命名的参数[1;2;3] 并返回f:('a -&gt; int -&gt; 'a) -&gt; init:'a -&gt; 'a 类型的函数。让我们将此函数称为 foo。

    由于您要给出两个命名参数,标记为 addi,因此类型 'a 被推断为函数类型,类型为 add:'c -&gt; ~i:'d -&gt; 'e

    根据变量addi的类型,'c必须是int -&gt; int -&gt; int'd必须是int

    替换'a 类型中的这些值,我们得出'a 类型为add:(int -&gt; int -&gt; int) -&gt; i:int -&gt; 'e。 并将其替换为 foo 的类型(我很高兴有复制粘贴 ;-),它的类型是

    f:((add:(int -> int -> int) -> i:int -> 'e)
        -> int
        -> (add:(int -> int -> int) -> i:int -> 'e))
    -> init:(add:(int -> int -> int) -> i:int -> 'e)
    -> (add:(int -> int -> int) -> i:int -> 'e)
    

    删除不必要的括号,并将 alpha 转换(即重命名)'e'a,我们得到 ​​p>

    f:((add:(int -> int -> int) -> i:int -> 'a)
        -> int
        -> add:(int -> int -> int) -> i:int -> 'a)
    -> init:(add:(int -> int -> int) -> i:int -> 'a)
    -> add:(int -> int -> int) -> i:int -> 'a
    

    那是 foo 的类型。但请记住,您将两个参数传递给 foo,标记为 ~add~i。所以最后得到的值不是add:(int -&gt; int -&gt; int) -&gt; i:int -&gt; 'a 类型,而是'a 类型。编译器返回的示例的整个类型是

    f:((add:(int -> int -> int) -> i:int -> 'a)
        -> int
        -> add:(int -> int -> int) -> i:int -> 'a)
    -> init:(add:(int -> int -> int) -> i:int -> 'a)
    -> 'a
    

    【讨论】:

    • 哇——真是一团糟!不过确实有道理,非常感谢!
    猜你喜欢
    • 2016-12-23
    • 2014-07-05
    • 2018-03-18
    • 1970-01-01
    • 2012-12-09
    • 1970-01-01
    • 2010-11-28
    • 2011-03-21
    • 1970-01-01
    相关资源
    最近更新 更多