content: {-# Language TemplateHaskell #-}
  
  -- from https://ocharles.org.uk/blog/guest-posts/2014-12-22-template-haskell.html
  
  import Language.Haskell.TH
  
  e1 :: IO Exp
  e1 = runQ [| 1 + 2 |]
  
  e2 :: Integer
  e2 = $( return (InfixE (Just (LitE (IntegerL 1)))
                         (VarE (mkName "+"))
                         (Just (LitE (IntegerL 2)))
                 )
        )
  
  fibs :: [Integer]
  fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
  
  fibQ :: Int -> Q Exp
  fibQ n = [| fibs !! n |]
  
  -- e3 gives stage restriction, need to import this module to get it
  -- e3 = $(fibQ 22)
  
  e4 = $(runQ [| fibs !! $( [| 8 |]) |])
  
  e5 :: IO Exp
  e5 = runQ [| 1 + 2 |]
  
  e6 :: IO [Dec]
  e6 = runQ [d|x = 5|]
  
  e7 :: IO Type
  e7 = runQ [t|Int|]
  
  e8 :: IO Pat
  e8 = runQ [p|(x,y)|]
  
  myExp :: Q Exp; myExp = runQ [| 1 + 2 |]
  
  e9 = runQ(myExp) >>= putStrLn.pprint
  
  -- ---------------------------------------------------------------------
  
  isPrime :: (Integral a) => a -> Bool
  isPrime k | k <=1 = False | otherwise = not $ elem 0 (map (mod k)[2..k-1])
  
  nextPrime :: (Integral a) => a -> a
  nextPrime n | isPrime n = n | otherwise = nextPrime (n+1)
  
  -- returns a list of all primes between n and m, using the nextPrime function
  doPrime :: (Integral a) => a -> a -> [a]
  doPrime n m
          | curr > m = []
          | otherwise = curr:doPrime (curr+1) m
          where curr = nextPrime n
  
  -- and our Q expression
  primeQ :: Int -> Int -> Q Exp
  primeQ n m = [| doPrime n m |]
  
  -- stage restriction on e10
  -- e10 = $(primeQ 0 67)
  
  -- ---------------------------------------------------------------------
  
  e11 = $(stringE . show =<< reify ''Bool)
  
  -- stage restriction e12
  -- e12 = $(stringE . show =<< reify 'primeQ)
  