For any one interested in what's going on here, the approach is roughly this:
* Create some basic tokens that represent operations in some domain
* Define an interpreter for those tokens, ie., the operation each token corresponds to
* Define a program as a sequence of these tokens
* Evaluate the program
To make this somewhat more efficient and correct, you can use the type system to define the tokens (eg., `interface ADD {}` becomes the `ADD` token). And use generics to sequence the tokens (eg., `ADD< ADD<CONST, CONST>, ...>`) with the runtime still having the actual values (so, roughly, `ADD<CONST, CONST> = new ADD(10, 10)`).
Then the interpreter becomes unwrapping those types in the order they're sequenced, extracting the actual runtime-held value, and performing the relevant operation (here, eg., adding two numbers).
If this seems an insane thing to do: it is. It becomes midly less insane if you have a syntax to do it in easily, and if your compiler is aware that you're doing it (ie., haskell).
Some much more basic version of this could be useful, in a real-world system, as a compile-time alternative to what might otherwise be a stringly-typed DSL.
Eg., program = [new Search<Query>("blah"), ...]; run(program)
Well summarized. This general approach (create tokens/interpreter for tokens/program as token tree) can be found in other functional design patterns too, like the Free Monad pattern. Even decoupled from any one specific design pattern, I find myself reaching for this general approach when modeling a complex domain.
F# is gorgeous. For anyone dipping their toes into functional programming, the book Domain Modeling Made Functional by Scott Wlaschin [1] does a great job to get the basics of F# and, more importantly, how to use a functional, strongly-typed language to model a domain for business applications.
Very cool and interesting! Though I don't see myself using this in production code. Even without higher-kinded type tricks like this, type signatures already can become unreadable quickly when you use a functional programming style in C#.
* Create some basic tokens that represent operations in some domain
* Define an interpreter for those tokens, ie., the operation each token corresponds to
* Define a program as a sequence of these tokens
* Evaluate the program
To make this somewhat more efficient and correct, you can use the type system to define the tokens (eg., `interface ADD {}` becomes the `ADD` token). And use generics to sequence the tokens (eg., `ADD< ADD<CONST, CONST>, ...>`) with the runtime still having the actual values (so, roughly, `ADD<CONST, CONST> = new ADD(10, 10)`).
Then the interpreter becomes unwrapping those types in the order they're sequenced, extracting the actual runtime-held value, and performing the relevant operation (here, eg., adding two numbers).
If this seems an insane thing to do: it is. It becomes midly less insane if you have a syntax to do it in easily, and if your compiler is aware that you're doing it (ie., haskell).
Some much more basic version of this could be useful, in a real-world system, as a compile-time alternative to what might otherwise be a stringly-typed DSL.
Eg., program = [new Search<Query>("blah"), ...]; run(program)