ML parameterised modules in Julia.
@sig struct ... end
: define module signatures, likesig
in OCaml.@structure struct ... end
: define module structures, likestruct
in OCaml.@open ModuleType Module
: using module, likeopen
in OCaml.@open ModuleType Module body
: using module when evaluatingbody
, likelet open
in OCaml.
using ParameterisedModule
# this is the module type declaration
@sig struct NatAlgebra
struct Eltype end # this is type declaration
succ :: Function
zero :: Eltype
end
# make a module `num_nat`, whose module type is NatAlgebra
num_nat = @structure struct NatAlgebra
Eltype = Int
succ(x) = x + 1
zero = 0
end
@open NatAlgebra num_nat begin
println(succ(succ(zero))) # 2
end
println(succ(succ(zero)))
# ERROR: UndefVarError: succ not defined
str_nat = @structure struct NatAlgebra
Eltype = String
succ(x) = "succ($x)"
zero = "zero"
end
@open NatAlgebra str_nat begin
println(succ(succ(zero))) # succ(succ(zero))
end
An example(word-algebra) from the section Algebra of Oleg's tagless final lectures.
Functor = Function
@sig struct TF{Eltype}
e :: Eltype
end
TFZero(nat :: NatAlgebra) =
@structure struct TF{nat.Eltype}
e = nat.zero
end
word_algebra =
@structure struct NatAlgebra
Eltype = Functor
zero = TFZero
succ(T1) =
function (N::NatAlgebra)
@structure struct TF{N.Eltype}
e = N.succ(T1(N).e)
end
end
end
@sig struct H
h :: Function
end
HTFC(N::NatAlgebra) =
@structure struct H
h(T) = T(N).e
end
using Test
@open H HTFC(num_nat) begin
@test h(word_algebra.zero) == num_nat.zero
case(x::Functor) =
h(word_algebra.succ(x)) == num_nat.succ(h(x))
words = Functor[TFZero]
for i = 1:100
push!(words, word_algebra.succ(words[end]))
end
@test all(words) do x; case(x) end
end