Question

Just a quick question. I'm wondering if there is a infix function composition operator in OCaml defined in the standard library (or in Jane Street's Core or in Batteries) like the (.) function in Haskell which saves us a lot parentheses since we can write (f . g . h) x instead of the less appealing f (g (h x))).

Thanks folks.

Was it helpful?

Solution

The answer here is the same as for flip :-). Function composition isn't defined in the OCaml standard library. In this case, it isn't something I miss once in a while, I miss it all the time.

The OCaml Batteries Included project defines function composition (in the order you give) using the operator -| in the BatStd module. As lukstafi points out (see below), this operator will apparently change to % in a future release of Batteries. (I've verified this in their source tree.)

As far as I can see, the Jane Street Core project doesn't define a function composition operator. It defines a function compose in the Fn module.

OTHER TIPS

I just want to add that the operator is fairly easy to include, in F# it's simply defined as:

let (<<) f g x = f(g(x));;

which has the type signature: val ( << ) : f:('a -> 'b) -> g:('c -> 'a) -> x:'c -> 'b doing exactly what you need...

(f << g << h) x = f(g(h(x))

so you don't need the batteries project if you don't have to

I'd like to add that the reason it looks like << is, as you might guess, because the >> operator does the opposite:

let (>>) f g x = g(f(x));;

(f >> g >> h) x = h(g(f(x))

There is Fn.compose function in Core, but it is not an infix operator. Also, it is implemented as a regular function and has runtime overhead.

In practice, it is pretty convenient to use pipe operator. It has no runtime overhead as implemented directly in compiler (starting from 4.00). See Optimized Pipe Operators for more details.

Pipe operator is available as '|>' in Core. So, you can rewrite your expression as following: h x |> g |> f

The use of an infix composition operator seems to be discouraged. (see this discussion).

You can write f @@ g @@ h x instead of f (g (h x))).

In Containers (yet another stdlib replacement for Ocaml), the function composition operator is called % and can be found in the CCFun module:

open Containers
open Fun

let is_zero n = (n = 0)

let nonzeros = List.filter (not % is_zero) [0;1;2;3;0]

Maybe that could help you.

let identite f = f
let (>>) = List.fold_right identite

test:

# let f=fun x-> x+1 and
      g=fun x-> x*2 and
      h=fun x-> x+3;;

# [f;g;h] >> 2;;
- : int = 11
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top