Can I universally quantify a lambda argument in an OCaml function?

Viewed 73

I noticed that I cannot do the following in OCaml:

# let foo (f : 'a -> unit) = f 1; f "s";;
Error: This expression has type string but an expression was expected of type
         int

In Haskell, this could be resolved by universally quantifying the input function f using Rank2Types:

{-# LANGUAGE Rank2Types #-}

foo :: (forall a. a -> ()) -> ()
foo f = let a = f 1 in f "2"

How can I get similar exposure to this in OCaml?

1 Answers

OCaml only supports semi-explicit higher-rank polymorphism: polymorphic functions arguments must be boxed either inside a record with polymorphic field:

type id = { id: 'a. 'a -> 'a }
let id = { id=(fun x -> x) }
let f {id} = id 1, id "one"

or inside an object

let id' = object method id: 'a. 'a -> 'a = fun x -> x end
let f (o: <id:'a. 'a -> 'a>) = o#id 1, o#id "one"

Beyond the syntactic heaviness, this explicit boxing of polymorphic functions has the advantage that it works well with type inference while still requiring only annotations at the definition of record types or the methods.

Related