composite-base-0.1.0.0: src/Composite/TH.hs
module Composite.TH where
import BasicPrelude
import Control.Lens (_1, _head, each, over, toListOf)
import Data.Char (toLower)
import Data.Proxy (Proxy(Proxy))
import Language.Haskell.TH (Q, Body(NormalB), Dec(SigD, ValD), Pat(VarP), Type(ConT), mkName, nameBase)
import Language.Haskell.TH.Lens (_TySynD)
-- |Make 'Proxy' definitions for each of the @type@ synonyms in the given block of declarations. The proxies have the same names as the synonyms but with
-- the first letter lowercased.
--
-- For example:
--
-- @
-- withProxies [d|
-- type FFoo = "foo" :-> Int
-- |]
-- @
--
-- Is equivalent to:
--
-- @
-- type FFoo = "foo" :-> Int
-- fFoo :: Proxy FFoo
-- fFoo = Proxy
-- @
--
-- __Note:__ the trailing @|]@ of the quasi quote bracket has to be indented or a parse error will occur.
withProxies :: Q [Dec] -> Q [Dec]
withProxies qDecs = do
decs <- qDecs
proxyDecs <- traverse proxyDecForName (toListOf (each . _TySynD . _1) decs)
pure $ decs <> concat proxyDecs
where
proxyDecForName tySynName = do
let tySynType = pure $ ConT tySynName
proxyName = mkName . over _head toLower . nameBase $ tySynName
proxyType <- [t|Proxy $tySynType|]
proxyVal <- [|Proxy|]
pure
[ SigD proxyName proxyType
, ValD (VarP proxyName) (NormalB proxyVal) []
]