Edit: While this answer holds theoretical value, you want to read neo's answer nowadays.
With parametric polymorphism, no. With ad-hoc polymorphism, yes.
For some type t, define a module,
module type Semigroup = sig
type t
val add : t -> t -> t
end
and some utility functions like partialsums
that rely on this inside a functor,
module Utils (S : Semigroup) = struct
let partialsums xs =
match xs with
| [] -> []
| (x::xs) ->
List.rev (snd (List.fold_left
(fun (acc, ys) x -> let y = S.add acc x in (y, y::ys)) (x, [x]) xs))
end
you can get the partialsums
specialized to particular types t,
module IntUtils = Utils(struct type t = int
let add = (+) end)
module FloatUtils = Utils(struct type t = float
let add = (+.) end)
let int_test = IntUtils.partialsums [1; 2; 3; 4] ;;
let float_test = FloatUtils.partialsums [1.0; 2.0; 3.0; 4.0]
which is kind of cool, but also a little tedious; you still have to prefix your functions with something type-specific, but at least you only have to write the functions once. This is just the module system being awesome.
With modular implicits, yes, yes, yes!
With Modular Implicits (2014) by White, Bour and Yallop, you can write,
implicit module Semigroup_int =
type t = int
let add = (+)
end
implicit module Semigroup_float =
type t = float
let add = (+.)
end
implicit module Semigroup_string =
type t = string
let add = (^)
end
let add {S : Semigroup} x y = S.add x y
which will allow the definition of a generic and overloaded partialsums
,
let partialsums xs =
match xs with
| [] -> []
| (x::xs) ->
List.rev (snd (List.fold_left
(fun (acc, ys) x -> let y = add acc x in (y, y::ys)) (x, [x]) xs))
so now it does work equally well for ints and floats!
let int_test = partialsums [1; 2; 3; 4] ;;
let float_test = partialsums [1.0; 2.0; 3.0; 4.0]
let string_test = partialsums ["a"; "b"; "c"; "d"]
There have apparently been several attempts at unifying the ML module system and Haskell's notion of type classes. See e.g. Modular Type Classes (2007) by Dreyer, Harper and Chakravarty for a good background story.
+
and+.
) to build the partial sums since there is no polymorphic addition operator, right? – Bickart