# Are there idioms in Julia for fast Algebraic Data Types (ADT)?

Hello @thautwarm,

thanks for point to tagless final style - intriguing! … I have tried to read into the topic given your example, as well as from this Haskell introduction. I have tried to follow the latter introduction in Julia language and came across a problem when trying to extend an existing `SYM`. As extensibility is one of the features of the tagless final approach, I was wondering how to go about it in Julia?

Here is my code:

``````# http://okmij.org/ftp/tagless-final/course/index.html#lecture

## Intro2.hs
lit :: FLIT
neg :: FNEG
end

function lit(v)
function (sym::ExpSYM)
sym.lit(v)
end
end

function neg(v)
function (sym::ExpSYM)
sym.neg(v(sym))
end
end

function (sym::ExpSYM)
end
end

## Implement evaluation for repr = Int
evaluate =
let lit(v::Int) = v,
neg(v::Int) = -v,
add(e1::Int, e2::Int) = e1 + e2
end

@show tf1(evaluate)
@code_warntype tf1(evaluate)

## Implement view for repr = String
view =
let lit(v::Int) = "\$v",
neg(v::String) = "(-\$v)",
add(e1::String, e2::String) = "(\$e1 + \$e2)"
end

@show tf1(view)

## ExtF.hs
struct MulSYM{FMUL}
mul::FMUL
end

function mul(term1, term2)
function (sym::MulSYM)
sym.mul(term1(sym), term2(sym))
end
end

## Implement evaluation for repr = Int
evaluate =
let mul(e1::Int, e2::Int) = e1 * e2
MulSYM(mul)
end

tfm1(evaluate) ## FAILS
# ERROR: LoadError: MethodError: no method matching (::var"#9#10"{var"#5#6"{Int64},var"#7#8"{var"#17#18"{var"#5#6"{Int64},var"#5#6"{Int64}}}})(::MulSYM{var"#mul#19"})
# Closest candidates are:
# #9(::ExpSYM) at /Users/Markus/.julia/dev/myplayground/playground/finaltagless_lecture.jl:24
# Stacktrace:
# [1] top-level scope at /Users/Markus/.julia/dev/myplayground/playground/finaltagless_lecture.jl:72
# [2] include_string(::Function, ::Module, ::String, ::String) at /Applications/Julia-1.5.app/Contents/Resources/julia/lib/julia/sys.dylib:?
# in expression starting at /Users/Markus/.julia/dev/myplayground/playground/finaltagless_lecture.jl:72
``````

Typeclasses should be interpreted as interfaces here, but you’re using Julia structs.
So far there is no way to give a type indicating the existence of specific fields.