Template Haskell and Quasi-Quotes

TH increases compile times and complicates cross-compilation. Prefer GHC.Generics or DerivingVia when they're sufficient. Typed TH (Code Q a, [|| ... ||]) gives type-checked splices.

{-# LANGUAGE TemplateHaskell #-}
-- Template Haskell: compile-time metaprogramming (generate code from code)
module Power where
import Language.Haskell.TH

-- Generate an unrolled power function at compile time: \x -> x * x * ... * x
power :: Int -> Q Exp
power 0 = [| const 1 |]
power n = [| \x -> x * $(power (n - 1)) x |]

-- Main.hs (TH splices must use definitions from another module)
-- cube :: Int -> Int
-- cube = $(power 3)

-- Reify: inspect existing declarations
-- $(stringE . show =<< reify ''Maybe)

-- Common TH uses in libraries:
--   makeLenses ''Person          (lens)
--   deriveJSON defaultOptions ''Person   (aeson)
--   persistent models, Yesod routes, singletons, file-embed
{-# LANGUAGE QuasiQuotes #-}
import Text.RawString.QQ (r)
import Data.String.Interpolate (i)

jsonTemplate :: String
jsonTemplate = [r|{"raw": "string with \n no escapes"}|]

greet :: String -> String
greet name = [i|Hello, #{name}! You have #{length name} letters.|]