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

**URL:** <https://discourse.julialang.org/t/are-there-idioms-in-julia-for-fast-algebraic-data-types-adt/37244>\
**Category:** General Usage\
**Created:** [April 8, 2020, 9:14pm UTC](https://discourse.julialang.org/t/are-there-idioms-in-julia-for-fast-algebraic-data-types-adt/37244 "2020-04-08T21:14:23Z")\
**Posts on this page:** 2\
**Page:** 3

<div class="post-metadata">

**Author:** ![magonser](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/magonser/32/18998_2.png) [@magonser](https://discourse.julialang.org/u/magonser)\
**Post date:** [September 20, 2020, 9:04pm UTC](https://discourse.julialang.org/t/are-there-idioms-in-julia-for-fast-algebraic-data-types-adt/37244/41 "2020-09-20T21:04:41Z")

</div>

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](http://okmij.org/ftp/tagless-final/course/index.html#lecture). 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?

On the top of my head, I don’t see how to solve the issue - have you thought about this yet?

Here is my code:

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

## Intro2.hs
struct ExpSYM{FLIT, FNEG, FADD}
    lit :: FLIT
    neg :: FNEG
    add :: FADD
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 add(term1, term2)
    function (sym::ExpSYM)
        sym.add(term1(sym), term2(sym))
    end
end

tf1 = add(lit(8), neg(add(lit(1), lit(2))))

## Implement evaluation for repr = Int
evaluate = 
    let lit(v::Int) = v,
        neg(v::Int) = -v,
        add(e1::Int, e2::Int) = e1 + e2
        ExpSYM(lit, neg, add)
    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)"
        ExpSYM(lit, neg, add)
    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

tfm1 = add(lit(7), neg(mul(lit(1), lit(2))))

## 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

```

---

<div class="post-metadata">

**Author:** ![thautwarm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thautwarm/32/37760_2.png) [@thautwarm](https://discourse.julialang.org/u/thautwarm)\
**Post date:** [October 22, 2020, 8:11pm UTC](https://discourse.julialang.org/t/are-there-idioms-in-julia-for-fast-algebraic-data-types-adt/37244/42 "2020-10-22T20:11:51Z")

</div>

> [@magonser](#):
>
> `MulSYM`

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.

[Previous page](https://discourse.julialang.org/t/are-there-idioms-in-julia-for-fast-algebraic-data-types-adt/37244.md?page=2)
