4 ms·
I didn't describe a mental model difference, but an actual factual difference in how it works. You can't add more types to a sum type, without modifying the sum
by 3cats-in-a-coat 3y ago
I didn't describe a mental model difference, but an actual factual difference in how it works. You can't add more types to a sum type, without modifying the sum type, which is a deal breaker for this use.
- js8 3y ago> You can't add more types to a sum type, without modifying the sum type, which is a deal breaker for this use. Honestly, why is it a deal breaker? We are talking about a small DSL with a handful of primitives in the sum type. I am asking because I have seen people advocate against if/case/pattern matching (FP) in favor of overloading (OOP) approach, without any consideration of the readability and simplicity of the former. I would understand that if you need to extend a sum type across module boundary, for example give this ability to a user of a library, then the latter approach makes sense (although in FP, this can be also done with typeclasses). But I don't really see the need here.
- noelwelsh 3y agoI agree. As this comment said: https://news.ycombinator.com/item?id=36858774 https://news.ycombinator.com/item?id=36858774 and I glossed over in "two different ways that have different tradeoffs", the data vs codata approach gives you orthogonal extensibility. (Note the original article didn't talk about extensibility at all.) In a DSL context you usually want new transformations (debuggers, pretty printers, etc.) on a fixed language. For this the FP / data approach is ideal. In some cases you want fixed transformations on an extensible language. An example is a visualization DSL. There are limitless visualizations but the operation you want to use on them is always the same: draw it. For this the OOP / codata approach is ideal. So choose the implementation technique that best suits your problem domain (and your implementation language.)
- js8 3y ago> An example is a visualization DSL. Interesting. I would say, this is not a DSL, but rather co-DSL. I can't really provide a formal definition right now, but I feel like primitives of DSL compose in the input of the evaluation function, while the primitives of co-DSL compose in the output of the evaluation function. In both cases, the evaluation function is fixed by the DSL's implementation. That's why DSL has a syntax tree (on input), but co-DSL has a tree of output widgets.
- noelwelsh 3y agoThis feels like an interesting idea but I can't quite fully see it. If a DSL is: AST -eval-> Result where AST is fixed and Result varies (depending on the choice of eval). Then a coDSL is AST -eval-> Result where AST varies and Result is fixed ? This feels like a restatement of the difference in modularity / extensibility.