Understand Core's `Fn.const`
Asked Answered
B

2

8

Jane Street's Core lib has such a function: Fn.const.

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

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

val const : 'a -> 'b -> 'a
produces a function that just returns its first argument

I really don't understand it.

  1. What's the purpose of this function? In what scenario we have to use it?
  2. Why put (); first?
  3. Why not write it as let const c = fun () -> c? this will give a function taking unit as parameter and always returns initial c.
  4. If I do let f = const 5, f will become a function which takes '_a as parameter. What's the purpose of returning a function with weak polymorphic parameter?

p.s. I see that several functions inside Fn module all have (); before returning a function, what is the usage of ();?

Brittnybritton answered 16/4, 2014 at 21:38 Comment(4)
Can you clarify question 2? How else could it have been written (other than leaving out the ())?Escrow
@Escrow edited, actually question 2 was redundant as of current point 2 and 3Brittnybritton
Is your last question just a rehash of the first, or am I missing something?Escrow
@Escrow you actually answered it while you answer current question 3.Brittnybritton
E
11

What's the purpose of this function? In what scenario we have to use it?

You'd use it in a context where a function taking an argument is required, but you don't actually care about the argument and just want to return the same value each time. A trivial example would be List.map (const 42) xs, which turns a list of n items into a list of n 42s.

A less silly (but more abstract) example would be a function that does something to produce a value, but under certain (say, in case the something did not succeed) conditions instead calls a user-supplied function to produce the value instead giving it some information about the situation as the argument. In some situations you might not case about the information and just return the same default value every time, so const would work here.

Why put (); first?

In its internal representation, as well as the generated code, the OCaml compiler actually has multi-argument functions. If you define a function like let f x y = ... or let f x = fun y -> ..., OCaml actually turns this into a 2-argument function (rather than a 1-argument function returning another function) internally. So when you then do f 1 2 to call it, that's a simple call to a 2-argument function, which is much more efficient than the alternative. However if you just do f x, some extra code will be generated to create the closure. This is less efficient than returning the closure directly.

So this optimization improves the performance when you call a function with all its arguments, but is actually counter-productive when you don't. Adding the () in front disables the optimization (because the function no longer has the form f x = fun y -> ...). Since const is meant to be called with just a single argument (directly calling const x y makes no sense as you could just as well write x), this improves the performance.

Why not write it as let const c = fun () -> c? this will give a function taking unit as parameter and always returns initial c.

Because then the function would only work in a context where a function taking unit is expected, which would be the vast minority of cases. For example List.map (const 42) xs would now only work if xs is a list of units, which it's almost certainly not.

Escrow answered 16/4, 2014 at 22:0 Comment(2)
Hi @sepp2k, I came back to the answer. OCaml actually turns this into a 2-argument function (rather than a 1-argument function returning another function) internally. I thought OCaml will turn multi-argument function to functions currying internally. According to what you say, it seems the other way around. Could you please describe more on that? What kind of optimisation OCaml has done to turn currying to multi-argument function? I am writing a post in typeocaml.com on higher-order functions, so please help.Brittnybritton
Have created a new question: #27625171Brittnybritton
U
3

1., 2. and 3.: see seppk's answer

4.: The OCaml type system is such that functions can't return polymorphic values. Your should read Gabriel's answers about it: What is the difference between 'a and '_l? overgeneralized curried fns

Umbria answered 17/4, 2014 at 9:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.