I've gone through a lot of your material now and I think it could be very 
valuable, thank you very much :D. But it is a complicated matter that I will 
need a bit of time to ponder on. There seems to be quite hard to find good 
examples of shallow vs deep embeddings. Shallow is using semantics and deep is 
using an AST, that's kinda what I've managed to get thus far. What would you 
say is the deep and shallow embeddings in Lux? The LuxNodes is deep as they are 
the AST but then it gets a bit fuzzier. I guess a proc as `transpose` would 
count as shallow as it is implemented using just the "language features" of the 
DSL. Operators as "+" and "*" feels especially hard to pinpoint. There's both 
the addition of two Funcs and also the addition between two LuxNodes. The first 
one being shallow and the second one deep. But at the same time the shallow 
version is just a wrapper for the deeper one acting on the LuxNode inside Func?

What I gathered from skimming through some of the linked papers is that as you 
said a solid core deep embedding (the smallest one to give the desired 
functionality basically) and then as much as possible is built as shallow 
embeddings. Two examples that could help me clear my mind is where mathematical 
functions (sin, exp, etc) and matrices:

1\. Mathematical functions such as exp and sin. We need the deep embedding to 
do simplifications like `exp(ln(x)) = x` but that limits us to the functions 
hardcoded in the code. Or perhaps we could use something like 
[this](https://github.com/mratsim/compute-graph-optim/blob/44ada700cdd95824d1702e9b843293d4aa86ccc4/e07_part1_var_ADTs_tables.nim#L15)
 to let the user define their own types along with a seq of simplification 
rules. Let's say someone created a library with a lot of functions this way for 
the symbolic library. Could the end-user then import the function-library and 
use the function-kinds defined there along with the default ones? Say someone 
writes a library with Bessel functions and they want to use them along with the 
sin and cos that comes by default.

2\. It feels like a symbolic matrix type should be doable just using shallow 
embeddings. Just a seq of SymbolicExpressions that uses the underlying 
operations available on the symbolic expressions. The "problem" with this 
approach is that it feels like it would be hard to generate Nim code at 
compileTime for this as the AST-builder doesn't know that it's a matrix it is 
working with. So perhaps it would need to be implemented in the deep embedding 
after all? 

Reply via email to