FWIW, I’ve written a single production compiler and used Haskell to do it. After the fact, I couldn’t imagine using anything else - Haskell seems to hit a real sweet spot for ‘language engineering’ work in general.
Haskell is an amazing language for writing your own compiler. If you are writing a compiler in another language you should genuinely consider switching.
Every time I have used Haskell for writing anything more complicated than a toy interpreter (e.g. a translator to a core language), I’ve been frustrated at how difficult it makes having multiple related ASTs and transformations between them. The two main “extensible” approaches (Data Types a la Carte and Finally Tagless) both have major issues, not the least of which being that they’re much harder to understand than a straightforward programming style. Have you had better luck?
All of the large compilers in Haskell (GHC, Agda, etc) just use a pretty vanilla sum type for ASTs. The other approaches (ala carte) are pretty experimental and I would never actually use them in a production system. If you want to get fancy you can maybe use Uniplate or Plated to do transformations, but even that isn’t necessary and probably only saves you a few lines at most. The simplest approach often works the best.
I can’t say I’ve experienced the same frustration when using a straightforward programming style. Our approach hasn’t used anything fancy (nothing like Data Types à la Carte, etc.) and has worked quite well. This is for a language with plenty of internal AST types, reasonably sophisticated type & module systems, etc.
Haskell is an amazing language for writing your own compiler. If you are writing a compiler in another language you should genuinely consider switching.
IIRC before Rust was self-hosting its compiler was written in OCaml, another great choice. Facebook’s Hack compiler is as well.
FWIW, I’ve written a single production compiler and used Haskell to do it. After the fact, I couldn’t imagine using anything else - Haskell seems to hit a real sweet spot for ‘language engineering’ work in general.
Gabriel Gonzalez wrote about this recently:
Every time I have used Haskell for writing anything more complicated than a toy interpreter (e.g. a translator to a core language), I’ve been frustrated at how difficult it makes having multiple related ASTs and transformations between them. The two main “extensible” approaches (Data Types a la Carte and Finally Tagless) both have major issues, not the least of which being that they’re much harder to understand than a straightforward programming style. Have you had better luck?
All of the large compilers in Haskell (GHC, Agda, etc) just use a pretty vanilla sum type for ASTs. The other approaches (ala carte) are pretty experimental and I would never actually use them in a production system. If you want to get fancy you can maybe use Uniplate or Plated to do transformations, but even that isn’t necessary and probably only saves you a few lines at most. The simplest approach often works the best.
I can’t say I’ve experienced the same frustration when using a straightforward programming style. Our approach hasn’t used anything fancy (nothing like Data Types à la Carte, etc.) and has worked quite well. This is for a language with plenty of internal AST types, reasonably sophisticated type & module systems, etc.
IIRC before Rust was self-hosting its compiler was written in OCaml, another great choice. Facebook’s Hack compiler is as well.