# 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:** 1\
**Showing post:** 20

<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:** [April 13, 2020, 10:59am UTC](https://discourse.julialang.org/t/are-there-idioms-in-julia-for-fast-algebraic-data-types-adt/37244/20 "2020-04-13T10:59:41Z")

</div>

Also, there is a technique to alter ADTs, called tagless final.

ADT approach is called initial approach in some context, and tagless final is called the final approach in this scope.

For your code, we can use tagless final, to achieve **stably typed Julia program** :

```julia
struct SYM{F1, F2}
    constant :: F1
    add :: F2
end

function constant(v)
    function (sym::SYM)
        sym.constant(v)
    end
end

function add(term1, term2)
    function (sym::SYM)
        sym.add(term1(sym), term2(sym))
    end
end

# self algebra
self = SYM(constant, add)

evaluate =
    let constant(v::Int) = v,
        add(l::Int, r::Int) = l + r
        SYM(constant, add)
    end

println(add(constant(2), constant(3))(evaluate))
@code_warntype add(constant(2), constant(3))(evaluate)

```

There’re no red points, try above codes in your Julia shell

```julia
5
Variables
  #self#::var"#17#18"{var"#15#16"{Int64},var"#15#16"{Int64}}
  sym::Core.Compiler.Const(SYM{var"#constant#19",var"#add#20"}(var"#constant#19"(), var"#add#20"()), false)

Body::Int64
1 ─ %1 = Base.getproperty(sym, :add)::Core.Compiler.Const(var"#add#20"(), false)
│ %2 = Core.getfield(#self#, :term1)::var"#15#16"{Int64}
│ %3 = (%2)(sym)::Int64
│ %4 = Core.getfield(#self#, :term2)::var"#15#16"{Int64}
│ %5 = (%4)(sym)::Int64
│ %6 = (%1)(%3, %5)::Int64
└── return %6

```

---

_[View the full topic](https://discourse.julialang.org/t/are-there-idioms-in-julia-for-fast-algebraic-data-types-adt/37244)._
