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