module type DOUBLE = {
type t
let double: t => t
}
let doubleList = (type a, nums: array<a>, mb: module(DOUBLE with type t = a)) => {
module D = unpack(mb)
Belt.Array.map(nums, D.double)
}
module DInt: DOUBLE with type t = int = {
type t = int
let double = x => x * 2
}
module DFloat: DOUBLE with type t = float = {
type t = float
let double = x => x *. 2.
}
doubleList([1, 2, 3], module(DInt))->Js.log
doubleList([4.3, 3.2, 32.2], module(DFloat))->Js.log
module type Comparable = {
type t
let compare: (t, t) => int
}
type comparable<'a> = module(Comparable with type t = 'a)
let compare = (type a, x, y, c: comparable<a>) => {
module C = unpack(c)
C.compare(x, y)
}
module IntCmp: Comparable with type t = int = {
type t = int
let compare = (x, y) => x - y
}
module FloatCmp: Comparable with type t = float = {
type t = float
let compare = (x, y) => x > y ? 1 : y > x ? -1 : 0
}
compare(1, 2, module(IntCmp))->Js.log
compare(1., 2., module(FloatCmp))->Js.log
module type Stringable = {
type t
let toString: t => string
}
module type MakePrinterType = (Item: Stringable) =>
{
let print: Item.t => string
}
module MakePrinter = (Item: Stringable) => {
let print = x => "Printer: " ++ Item.toString(x)
}
module StringableInt = {
type t = int
let toString = Js.Int.toString
}
module StringableFloat = {
type t = float
let toString = Js.Float.toString
}
let f = module(MakePrinter: MakePrinterType)
module IntPrinter = unpack(f)(StringableInt)
IntPrinter.print(45322)->Js.log
module FloatPrinter = MakePrinter(StringableFloat)
FloatPrinter.print(112.211)->Js.log