As a small ReScript learning exercise I’m using modules to model abstract algebraic semigroups. So far I have:
// A module interface for abstract semigroups:
module type Semigroup = {
type t
let op: (t, t) => t
}
// module interfaces can't have default functions so the
// semigroup laws need to be in a separate module:
module SemigroupLaws = (S : Semigroup) => {
let associative = (x: S.t, y: S.t, z: S.t) =>
S.op(x, S.op(y, z)) == S.op(S.op(x, y), z)
}
// Integers form a semigroup under addition (ignoring overflow):
module IntSemigroup: Semigroup with type t = int = {
type t = int
let op = (x: int, y: int) => x + y
}
// Integer semigroup addition as expected:
Console.log(IntSemigroup.op(2, 3))
But I think I’m missing or misunderstanding a technique to create an int
instance of SemigroupLaws
. Is this a use case for module functors?
module IntSemigroupLaws: SemigroupLaws(???)
Any advice much appreciated.