[Haskell-beginners] A seemingly simple use-case for Template Haskell

Mario Lang mlang at delysid.org
Wed Sep 28 13:06:53 UTC 2016


Hi.

As a long-term Lisp fan, and someone who always admired compile-time
code-generation, I wanted to at least do something simple with Template
Haskell once.

In a small project of mine, I have this basically auto-generated data
type:

-- Braille music code only uses the old 6-dot system.  We enumerate all
-- possible dot patterns to use the type system to avoid accidentally
-- specifying invalid dot patterns in the source code.
--
-- gen :: String
-- gen =
--     "data Braille = " ++ intercalate " | " ctors ++ " deriving (Enum, Eq)" where
--   ctors = "NoDots" : map ctorName [1..63] where
--     ctorName :: Int -> String
--     ctorName = (++) "Dot" . concatMap (show . succ) . flip filter [0..5] . testBit

data SixDots = NoDots | Dot1 | Dot2 | Dot12 | Dot3 | Dot13 | Dot23 | Dot123
             | Dot4 | Dot14 | Dot24 | Dot124 | Dot34 | Dot134 | Dot234
             | Dot1234 | Dot5 | Dot15 | Dot25 | Dot125 | Dot35 | Dot135
             | Dot235 | Dot1235 | Dot45 | Dot145 | Dot245 | Dot1245 | Dot345
             | Dot1345 | Dot2345 | Dot12345 | Dot6 | Dot16 | Dot26 | Dot126
             | Dot36 | Dot136 | Dot236 | Dot1236 | Dot46 | Dot146 | Dot246
             | Dot1246 | Dot346 | Dot1346 | Dot2346 | Dot12346 | Dot56 | Dot156
             | Dot256 | Dot1256 | Dot356 | Dot1356 | Dot2356 | Dot12356
             | Dot456 | Dot1456 | Dot2456 | Dot12456 | Dot3456 | Dot13456
             | Dot23456 | Dot123456
             deriving (Bounded, Enum, Eq, Read, Show)

So, while actually quite simple, this looks like an opportunity to use
Template Haskell for me.  In other words, I want to figure out what is
necessary to generate this data type with TH, instead of the gen
function that basically generates a piece of plain Haskell code.

I have been reading "A practical Template Haskell Tutorial"[1] but I find
it a little bit too terse to actually solve this very little riddle on
my own.

For one, I find it confusing that some TH functions return "Q Dec" while
others just return Dec.  I am aware that this is some sort of Monad for
the TH system, but I have never seen it explained anywhere.

Also, all the examples I can find seem to be mostly focused in
generating Q Exp or similar, but I didn't really find an example
for Q Dec.

I realize this should be simple to figure out on my own, but it
apparently is not.  I have tried to wrap my head around this on my own
at least three times now, but always stopped after an hour or two due to
frustration.  Is there some comprehensive TH documentation I haven't
seen yet?  Could you please give me enough of a head-start that I
actually manage to write something which can generate this simple data
type above?

[1] https://wiki.haskell.org/A_practical_Template_Haskell_Tutorial
-- 
CYa,
  ⡍⠁⠗⠊⠕


More information about the Beginners mailing list