blog

Batteries 2.0: Composition and application

Posted on February 24, 2013

A while back, I discussed an implementation of the application operator (Haskell’s $) in OCaml. In the closing section of that post, a couple of problems were raised regarding treatment of associativity and composition in OCaml Batteries. These issues have been addressed in Batteries 2.0, released in January 2013; the improvements are outlined here.

Quick recap

Batteries 1.x defines the following operators for composition and application:

  • val ( -| ) : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b
    • “Function composition. f -| g is fun x -> f (g x). Mathematically, this is operator o.”
  • val ( **> ) : ('a -> 'b) -> 'a -> 'b
    • “Function application. f **> x is equivalent to f x. This [operator] may be useful for composing sequences of function calls without too many parenthesis.”

The problem pointed out in the comments section (now the closing Update) of the post was that

the precedence you’d expect coming from Haskell is inverted. We’d need to define a new application operator to address this problem as the commenter suggested…

Specifically, the following code sample was shown to exhibit surprising behaviour for anyone familiar with Haskell’s . and $,

# print_endline -| string_of_int **> succ **> sum [1; 2; 3];;
Error: This expression has type string but an expression was expected of type 'a -> string

What’s up, doc?

In Batteries 2.0, both operators have been renamed:

  • Composition:
    • (-|) is now (%)
  • Application:
    • (**>) is now (@@)

To appreciate the behaviour of the new operators, we can once again consult (a subsection of) the operator associativity table from the language manual:

Construction or operator Associativity
*... /... %... mod land lor lxor left
+... -... left
:: right
@... ^... right
=... <... >... |... &... $... left

A couple of things are worth noting:

  • The associativity of the application operator has changed.
    • (**>) is left associative, (@@) right.
    • As discussed in the original post, right associativity is an integral feature of the application operator.
  • In Batteries 1.x, application had higher precedence than composition.
    • (**>) is covered by the first row of the table, (-|) by the second.
    • As of Batteries 2.0, this precedence has been inverted.

No surprises

Reworking the above code sample for Batteries 2.0 is trivial—simply substitute (%) for (-|) and (@@) for (**>). With these changes in place, the code behaves as follows:

# print_endline % string_of_int @@ succ @@ sum [1; 2; 3];;
7
- : unit = ()

Crucially, the application operator has lower precedence than the composition operator and is right associative.

Returning to the definition of $ referenced at the outset of the original post,

This operator is redundant, since ordinary application (f x) means the same as (f $ x). However, $ has low, right-associative binding precedence, so it sometimes allows parentheses to be omitted.

it should be apparent that these new operators closely conform to Haskell’s treatment of application and composition (in particular, associativity and precedence), allowing for a straightforward translation of the above expression:

Prelude> putStrLn . show $ succ $ sum [1, 2, 3]
7

comments powered by Disqus