It seems that Template Haskell is often viewed by the Haskell community as an unfortunate convenience. It’s hard to put into words exactly what I have observed in this regard, but consider these few examples
- Template Haskell listed under “The Ugly (but necessary)” in response to the question Which Haskell (GHC) extensions should users use/avoid?
- Template Haskell considered a temporary/inferior solution in Unboxed Vectors of newtype’d values thread (libraries mailing list)
- Yesod is often criticized for relying too much on Template Haskell (see the blog post in response to this sentiment)
I’ve seen various blog posts where people do pretty neat stuff with Template Haskell, enabling prettier syntax that simply wouldn’t be possible in regular Haskell, as well as tremendous boilerplate reduction. So why is it that Template Haskell is looked down upon in this way? What makes it undesirable? Under what circumstances should Template Haskell be avoided, and why?
One reason for avoiding Template Haskell is that it as a whole isn’t type-safe, at all, thus going against much of “the spirit of Haskell.” Here are some examples of this:
Exp, but you don’t know if it is an expression that represents a[Char]or a(a -> (forall b . b -> c))or whatever. TH would be more reliable if one could express that a function may only generate expressions of a certain type, or only function declarations, or only data-constructor-matching patterns, etc.foothat doesn’t exist? Tough luck, you’ll only see that when actually using your code generator, and only under the circumstances that trigger the generation of that particular code. It is very difficult to unit test, too.TH is also outright dangerous:
IO, including launching missiles or stealing your credit card. You don’t want to have to look through every cabal package you ever download in search for TH exploits.Then there are some problems that make TH functions less fun to use as a library developer:
generateLenses [''Foo, ''Bar].forM_ [''Foo, ''Bar] generateLens?Qis just a monad, so you can use all of the usual functions on it. Some people don’t know this, and because of that, they create multiple overloaded versions of essentially the same functions with the same functionality, and these functions lead to a certain bloat effect. Also, most people write their generators in theQmonad even when they don’t have to, which is like writingbla :: IO Int; bla = return 3; you are giving a function more “environment” than it needs, and clients of the function are required to provide that environment as an effect of that.Finally, there are some things that make TH functions less fun to use as an end-user:
Q Dec, it can generate absolutely anything at the top-level of a module, and you have absolutely no control over what will be generated.