Understand Core `Fn.const`

Jane Street Core lib has this function: Fn.const .

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

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

val const: 'a →' b → 'a
creates a function that returns its first argument

I really don't get it.

  • What is the purpose of this feature? In which scenario should we use it?
  • Why put (); first of all?
  • Why not write it as let const c = fun () -> c ? this will give a function that takes unit as a parameter and always returns the starting c .
  • If I do let f = const 5 , f will become a function that takes '_a as a parameter. What is the purpose of returning a function with a weak polymorphic parameter?

ps I see that before the function returns, several functions inside the Fn module have (); what is the use of (); ?

+7
ocaml ocaml-core
source share
2 answers

What is the purpose of this feature? In which scenario should we use it?

You would use it in a context where you need a function that takes an argument, but you actually don't care about that argument and just want to return the same value every time. A trivial example: List.map (const 42) xs , which turns a list of n elements into a list of n 42s.

A less stupid (but more abstract) example would be a function that does something to produce a value, but under certain (for example, in case something failed) conditions, instead, calls a user-defined function to create the value instead, giving him some information about the situation as an argument. In some situations, you can ignore the information and just return the same default value each time, so const will work here.

Why put (); first?

In its internal representation, as well as the generated code, the OCaml compiler actually has functions with several arguments. If you define a function like let fxy = ... or let fx = fun y -> ... , OCaml actually turns this into a function with two arguments (and not a 1-argument function that returns another function) inside. Therefore, when you then execute f 1 2 to call it, it is a simple function call with two arguments, which is much more efficient than the alternative. However, if you just do fx , additional code will be created to create the closure. This is less efficient than returning a close directly.

Thus, this optimization improves performance when you call a function with all its arguments, but is actually counterproductive when you do not. Adding () in front disables optimization (because the function no longer has the form fx = fun y -> ... ). Since const supposed to be called with only one argument (direct invocation of const xy does not make sense, as you could also write x ), this improves performance.

Why not write it as let const c = fun () → c? this will give a function that takes one as a parameter and always returns the initial c.

Because then the function will work only in the context where the function accepting unit is expected, which will be a huge number of cases. For example, List.map (const 42) xs will now work only if xs is a list of units, which almost certainly will not.

+10
source share

1., 2. and 3: see seppk answer

4: A system such as OCaml is such that functions cannot return polymorphic values. You should read Gabriel's answers about this: What is the difference between 'a and' _l? overgeneralized curries fns

+3
source share

All Articles