OCaml functors, Haskell type classes, and multiple derivation
Asked Answered
P

1

18

It is well-known that OCaml has a parametric polymorphism and this leads to some limitations. Haskell, through its type classes, offers an ad hoc polymorphism, which is, obviously, very convenient in several situations. It is also well-known that the system of modules and functors of OCaml allows to create a kind of ad hoc polymorphism. See the great recent answer of Simon Shine here for instance.

My point is that it is possible in Haskell to create types that derive several types classes. For instance :

data Person = Person { firstName :: String
                 , lastName :: String
                 , age :: Int
                 } deriving (Eq, Show, Read)

This is very convenient to define types having several features (allowing values of type Person to support equality tests, be printable, and be readable in the given example).

My question is the following: Can we do the same, simply, in OCaml? By simply I mean with the ground syntax of the language and without many artifices.

To give a somewhat concrete example, suppose we have two OCaml signatures

module type Showable = sig
    type t
    val to_string : t -> string
end

module type Readable = sig
    type t
    val from_string : string -> t
end

The aim is to write a functor F parametrized by a module which implements both Showable and Readable.

Pulsatory answered 13/6, 2016 at 21:16 Comment(1)
This must be one of the best written question i've ever seen ! Hope someone will find an answer !Unpleasant
A
15

Sure, that's actually quite easy, use module inclusion.

module type S = sig
  include Showable
  include Readable with type t := t (* destructive substitution *)
end
    
module F ( M : S ) = struct
  let fake_id x = M.from_string @@ M.to_string x
end

Destructive substitution is explained in the manual: http://caml.inria.fr/pub/docs/manual-ocaml/extn.html#sec234
The rest is regular module stuff (see the manual for a complete explanation)

Some functor-heavy library rely on this kind of structural subtyping quite a lot. For example, each functor in ocamlgraph define its own module type argument. Here is an example with the Kruskal module. The functor expect a module of type Kruskal.G, which implements a subsignature of Sig.G (which is implemented by most graph modules).

Accrue answered 13/6, 2016 at 22:0 Comment(5)
Thanks, this is in fact quite easy! In some sense, can we say that the system of type classes of Haskell and those of modules and functor of OCaml are equivalent?Pulsatory
They're not equivalent. As described in Modular Type Classes, ML's module system is more flexible and general than Haskell's type classes, but don't allow recursion. Combining them means you don't have to write functor application manually, but you also avoid Haskell's problem of only one imported type class instance per type. See Stefan Wehr's ML Modules and Haskell Type Classes: A constructive Comparison pp. 107-110 for a summary of the differences.Tanh
Correction: Smarter persons than I point out; Oleg Kiselyov proved an equivalence between the two (given some dated definition of Haskell type classes), although I cannot find this article, while modern Haskell type classes are stronger than ML modules as they provide type-level functions. I'll avoid making any more bold statements and will go back to writing cool code snippets. ;-)Tanh
Here: Applicative translucent functors in Haskell (2004) by Oleg Kiselyov and Chung-chieh Shan.Tanh
The original link for Modular Type Classes is now broken. Here are two alternative locations: A and BOakman

© 2022 - 2024 — McMap. All rights reserved.