[ANN] ppx_mixins: slightly more elegant mixin syntax

Hello,

I’ve written a tiny ppx called ppx_mixins so that one can write:

type u [@@mixins Map.OrderedType + Printable]

which gets desugared to

type u
include Map.OrderedType with type t := u
include Printable with type t := u

Not much but increases readability in a codebase that uses the “mixin” pattern a lot

Constructing type signatures

One can also write

module type M = [%mixins Map.OrderedType + Printable]`
(* desugars to *)
module type M = sig 
   type t 
   include Map.OrderedType with type t := t
   include Printable with type t := t
end

In particular, if you also overcome the lack of support for e.g. pretty printing (or other features) in the standard library by extending functors:

module type Hashed_and_printable = sig
   include Stdlib.Hashtbl.HashedType
   val pp : Format.formatter -> t -> unit
end

module Make (T: Hashed_and_printable) = struct 
   include Stdlib.Hashtbl.Make(T)
   let pp = ...
end

You can instead write:

module Make(T: [%mixins Stdlib.Hashtbl.HashedType + Printable]) = struct 
   ...
end

Additional features

One can also override other types, e.g.

type u [@@mixins Mappable(key = int; value := v)]
(* desugars to *)
type u
include Mappable with type t := u and type key = int and type value := v

Limitations

  • No support for parametric types, e.g. with type 'a u = 'a v
  • No support for tuple and function types, e.g. with type t = int -> bool

This is because the preprocessor parses the payload as an expression, and these don’t parse nicely a expressions.
Deeper support (e.g. for mixins with type parameters) would probably also require language support.

2 Likes