1. 2
  1.  

  2. 2

    In Ocaml, this bit of ugliness is not needed. By not exposing the implementation type in the interface, one can have a type that is an int but is not usable as an int outside of the model. There is no added indirection or cost because the types disappear at compile-time, after they have been checked.

    foo.mli

    type t
    val of_int : int -> t
    val to_int : t -> int
    val add : t -> t -> t
    

    foo.ml

    type t = int
    let of_int i = i
    let to_int t = t
    let add = (+)
    

    Will compile:

    Foo.to_int (Foo.add (Foo.of_int 1) (Foo.of_int 2))
    

    Won’t compile:

    Foo.add 1 2