{-# LANGUAGE CPP #-}
{-# LANGUAGE LambdaCase #-}
module TH where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax (lift)
firstConstrForType :: String -> ExpQ
firstConstrForType typeName = lookupTypeName typeName >>= \case
Nothing -> fail $ "Type does not exist: " ++ typeName
Just name -> reify name >>= \case
#if MIN_VERSION_template_haskell(2,11,0)
TyConI (DataD _ _ _ _ cons _) -> firstConstr cons
TyConI (NewtypeD _ _ _ _ con _) -> firstConstr [con]
#else
TyConI (DataD _ _ _ cons _) -> firstConstr cons
TyConI (NewtypeD _ _ _ con _) -> firstConstr [con]
#endif
_ -> fail $ "Not a data type: " ++ typeName
where
firstConstr [] = fail $ "Data type has no constructors: " ++ typeName
firstConstr (c:_) = lift . nameBase =<< case c of
NormalC name _ -> pure name
RecC name _ -> pure name
_ -> fail $ "Weird constructor: " ++ typeName
explode :: String -> ExpQ
explode [] = fail "Cannot explode empty string"
explode xs = listE $ map (litE . stringL . (:[])) xs