Skip to content
Provide you the classic ways to write (Rust/Scala/Haskell-style) typeclasses/traits in Julia.
Julia
Branch: master
Clone or download

README.md

CanonicalTraits

Stable Dev Build Status Codecov

Trait Definition

@trait Monoid{A} begin
    mempty :: Type{A} => A
    # a method with two arguments
    (⊕)    :: [A, A] => A
end

Note, the form @trait A{B, C, D <: Number, E <: AbstractString} is supported as well.

Instance Definition

@implement Monoid{Int} begin
  mempty(::Type{Int}) = 0
  a ⊕ b = a + b
end


32 # 5
mempty(Int) # 0

More

julia> @trait Monoid{A} begin
                  mempty :: Type{A} => A
                  # a method with two arguments
                  (⊕)    :: [A, A] => A
              end


julia> @implement Monoid{Num} where Num <: Number begin
           mempty(::Type{Num}) = zero(Num)
           (a :: Num) ⊕ (b :: Num) = a + b
       end

julia> using BenchmarkTools

julia> 32
5

julia> 3.02
ERROR: MethodError: no method matching ⊕(::Float64, ::Int64)
Closest candidates are:
  ⊕(::A, ::A) where A

julia> """"
ERROR: Not implemented trait Monoid for (String).

julia> 3.02.0
5.0

julia> mempty(Int)
0

julia> mempty(Float32)
0.0f0

julia> @btime 100200
  0.018 ns (0 allocations: 0 bytes)
300

julia> @btime 100 + 200
  0.018 ns (0 allocations: 0 bytes)
300

Limitations

* Due to the limitations of dynamic language, the type parameters occurred in trait signature should occur in the argument of each trait methods. Also, cannot define constants/singletons for traits because it's a technique for static typing.

* For Haskell users: MultiParamTypeClasses is supported. FunctionalDependencies is supported as well but need an explicit inference rule, check test/runtests.jl and search Dot for more details.

@trait Dot{F, V} where {F = vect_infer_helper(V)} begin
    dot :: [V, V] => F
    gram_schmidt :: [V, Set{V}] => V
end

Cannot list out all limitations here, if any problem, please open an issue or e-mail me.

You can’t perform that action at this time.