module Data.Generics.Record (
RecordT,
isRecord,
recordT,
fields,
emptyRecord,
recordStructure) where
import Data.Data
import Data.Maybe
data RecordT a = RecordT
isRecord :: forall a . Data a => a -> Bool
isRecord _ = isJust (recordT :: Maybe (RecordT a))
recordT :: forall a. Data a => Maybe (RecordT a)
recordT = if isRecord' ra then Just ra else Nothing
where ra = (RecordT :: RecordT a)
isRecord' :: forall a. Data a => RecordT a -> Bool
isRecord' r = length cs == 1 && length (fields r) > 0
where cs = dataTypeConstrs . dataTypeOf $ (undefined :: a)
fields :: forall a. Data a => RecordT a -> [String]
fields _ = fs
where cs = dataTypeConstrs . dataTypeOf $ (undefined :: a)
fs = cs >>= constrFields
emptyRecord :: forall a. Data a => RecordT a -> a
emptyRecord _ = fromConstr . head . dataTypeConstrs . dataTypeOf $ (undefined :: a)
recordStructure :: forall a. Data a => RecordT a -> [(TypeRep, String)]
recordStructure a = zip (gmapQ typeOf (emptyRecord a)) $ fields a