如何阅读这段使用“~”和“:”的 OCaml 代码?

How do I read this piece of OCaml code that uses "~" and ":"?

我是 OCaml 的新手,在浏览一些代码时我看到了以下内容:

  let catch f m = M.bind m ~f:(
      function Error e -> f e
             | Ok x -
    )

据我所知,这是在定义一个 try/catch 块(我的理解是 OCaml 不使用单独的 catch 块)。 M.bind 是将 m 的结果传递给第二次计算的单子绑定运算符。 OCaml 参考手册说 ~ 用于标记参数,以便于理解它们在文档中的类型签名。然而,这是否意味着第二个计算(“function ..”)也被标记为 f??

带标签的参数与特定函数相关联。这意味着该函数有一个带有名称的参数。调用该函数时,您可以像这样指定名称和值:

 myfun ~name: value

如果这个调用有效,那么我们就知道 myfun 有一个名为 name.

的参数

为了比较,当您调用一个没有标记参数的函数时,调用看起来像这样:

myotherfun othervalue

接受命名参数的函数的定义如下所示:

let myfun ~name =
    ... expression involving name ...

例如,此函数根据您传递给它的任何内容生成一个单例列表:

let myfun ~name = [name]

在 OCaml 顶层 (REPL) 中对该函数的调用如下所示:

# myfun ~name: 44;;
- : int list = [44]

关键是这允许您在调用函数时按名称而不是按位置指定参数。您需要指定函数期望的名称。但是,如果一个函数有多个命名参数,您可以按任意顺序指定它们。

这些名称仅用于 OCaml 文档是不正确的。该手册告诉您的是,命名参数可以作为关于不同参数用途的良好文档。对于需要大量参数的函数尤其如此,如果其中一些参数类型相同,则更是如此。使用名称可以避免以错误的顺序指定它们的那种错误。

因此,您正在调用一个函数 M.bind,该函数具有一个名为 f 的带标签参数。按照惯例,名为 f 的参数用于将函数作为参数传递,这确实是这里发生的事情。

所以;你的问题似乎是第二个参数是否被标记。 M.bind 的第二个参数被标记为,是的。但价值可以是任何东西。值不受传递给函数的标签的影响。此外,您可以查看函数定义 function Error ... 并发现它没有任何带标签的参数。它只是一个接受 result 类型值的函数。

重复一下,这是一个函数定义:

function Error -> f e | Ok x -> g x

所以我们知道关于这个函数的一切。它绝对没有任何命名参数。