8

Jane Street 的 Core lib 有这样一个功能:Fn.const.

https://github.com/janestreet/core_kernel/blob/master/lib/fn.ml

let const c = (); fun _ -> c

val const : 'a -> 'b -> 'a
产生一个只返回其第一个参数的函数

我真的不明白。

  1. 这个函数的目的是什么?在什么场景下我们必须使用它?
  2. 为什么要();放在第一位?
  3. 为什么不写成let const c = fun () -> c? 这将给出一个unit作为参数的函数并始终返回 initial c
  4. 如果我这样做let f = const 5f将成为一个以'_a参数为参数的函数。返回具有弱多态参数的函数的目的是什么?

ps 我看到Fnmodule里面的几个函数都();在返回一个函数之前,有什么用();

4

2 回答 2

11

这个函数的目的是什么?在什么场景下我们必须使用它?

您将在需要接受参数的函数的上下文中使用它,但您实际上并不关心参数,而只想每次返回相同的值。一个简单的例子是List.map (const 42) xs,它将 n 个项目的列表转换为 n 42s 的列表。

一个不那么愚蠢(但更抽象)的例子是一个函数,它做某事来产生一个值,但在某些情况下(比如,如果某事没有成功),而是调用用户提供的函数来产生值而不是给它一些有关情况的信息作为论据。在某些情况下,您可能不会考虑信息,并且每次都返回相同的默认值,因此const可以在这里工作。

为什么放 (); 第一的?

在其内部表示以及生成的代码中,OCaml 编译器实际上具有多参数函数。如果您定义类似let f x y = ...or的函数let f x = fun y -> ...,OCaml 实际上在内部将其转换为 2 参数函数(而不是返回另一个函数的 1 参数函数)。因此,当您f 1 2调用它时,这是对 2 参数函数的简单调用,这比替代方法更有效。但是,如果您只是这样做f x,将生成一些额外的代码来创建闭包。这比直接返回闭包效率低。

因此,当您使用所有参数调用函数时,这种优化会提高性能,但如果不这样做,实际上会适得其反。添加()前面禁用优化(因为函数不再具有形式f x = fun y -> ...)。由于const只需要一个参数来调用(直接调用const x y没有意义,你也可以 write x),这提高了性能。

为什么不写成 let const c = fun () -> c?这将给出一个以单位为参数的函数,并始终返回初始 c。

因为那样的话,该函数只能在unit预期会采用函数的情况下工作,这将是极少数情况。例如List.map (const 42) xs,现在只有在xs是一个单位列表时才有效,几乎可以肯定不是。

于 2014-04-16T22:00:45.073 回答
3

1.、2. 和 3.:见 seppk 的回答

4.:OCaml 类型系统使得函数不能返回多态值。您应该阅读 Gabriel 对此的回答:'a 和 '_l 有什么区别? 过度概括的咖喱 fns

于 2014-04-17T09:17:38.130 回答