I have many programs written in OCaml, some of them use functors. Now, I am considering of writing and re-writing a part of code in F# (to benefit some advantages that OCaml doe
As you noticed, F# doesn't have functors - F# modules cannot be parameterized by types. You can get similar results in F# using the object oriented parts of the language - interfaces, generic classes and inheritance.
Here's a heavy handed approach at emulating your example.
type Comparison = Less | Equal | Greater
/// Interface corresponding to ORDERED_TYPE signature
type IOrderedType<'a> =
abstract Value: 'a
abstract Compare: IOrderedType<'a> -> Comparison
/// Type that implements ORDERED_TYPE signature, different instantiations
/// of this type correspond to your OrderedInt/OrderedString modules.
/// The 't: comparison constraint comes from the fact that (<) operator
/// is used in the body of Compare.
type Ordered<'t when 't: comparison> (t: 't) =
interface IOrderedType<'t> with
member this.Value = t
member this.Compare (other: IOrderedType<'t>) =
if t = other.Value then Equal else if t < other.Value then Less else Greater
/// A generic type that works over instances of IOrderedType interface.
type Set<'t, 'ot when 't: comparison and 'ot :> IOrderedType<'t>> (coll: IOrderedType<'t> list) =
member this.Values =
coll |> List.map (fun x -> x.Value)
member this.Add(x: 't) =
let rec add (x: IOrderedType<'t>) s =
match coll with
| [] -> [x]
| hd::tl ->
match x.Compare(hd) with
| Equal -> s (* x is already in s *)
| Less -> x :: s (* x is smaller than all elements of s *)
| Greater -> hd :: add x tl
Set<'t, 'ot>(add (Ordered(x)) coll)
static member Empty = Set<'t, 'ot>(List.empty)
/// A helper function for Set.Add. Useful in pipelines.
module Set =
let add x (s: Set<_,_>) =
s.Add(x)
/// Type aliases for different instantiations of Set
/// (these could have easily been subtypes of Set as well)
type StringSet = Set>
type IntSet = Set>
let try1 () = Set.add "foo" StringSet.Empty
let try2 () = Set.add 2 IntSet.Empty
try1().Values
try2().Values