module Record.Introspection where
import BasePrelude hiding (Proxy)
#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 707
import Data.Proxy
#endif
import Foreign.Storable (Storable (sizeOf))
import GHC.TypeLits
import Language.Haskell.TH
import Record.Types
class HasFieldNames a where
fieldNames :: a -> [String]
return $ flip map [1..24] $ \arity ->
let typeName = mkName $ "Record" <> show arity
recordType = foldl (\a i -> AppT (AppT a (SigT (VarT (mkName ("n" <> show i))) (ConT ''Symbol)))
(VarT (mkName ("v" <> show i))))
(ConT typeName)
[1 .. arity]
nVals = map (\i -> "n" <> show i) [1..arity]
nTVals = map (VarT . mkName) nVals
#if MIN_VERSION_template_haskell(2,10,0)
mkContext c t = AppT (ConT (mkName c)) t
#else
mkContext c t = ClassP (mkName c) [t]
#endif
fieldNames' = ListE $ flip map nTVals
#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 707
(\n -> AppE (VarE (mkName "symbolVal"))
(SigE (ConE (mkName "Proxy")) (AppT (ConT (mkName "Proxy")) n)))
context = map (\n -> mkContext "KnownSymbol" n) nTVals
#else
(\n -> AppE (VarE (mkName "fromSing"))
(SigE (VarE (mkName "sing")) (AppT (ConT (mkName "Sing")) n)))
context = map (\n -> mkContext "SingI" n) nTVals
#endif
fieldNamesFun = FunD (mkName "fieldNames")
[Clause [WildP] (NormalB fieldNames') []]
in InstanceD context
(AppT (ConT (mkName "HasFieldNames")) recordType)
[fieldNamesFun]
class HasFieldDims a where
fieldDims :: a -> [Int]
return $ flip map [1..24] $ \arity ->
let typeName = mkName $ "Record" <> show arity
recordType = foldl (\a i -> AppT (AppT a (SigT (VarT (mkName ("n" <> show i))) (ConT ''Symbol)))
(AppT (VarT (mkName ("l" <> show i))) (VarT (mkName ("v" <> show i)))))
(ConT typeName)
[1 .. arity]
vVals = map (\i -> "v" <> show i) [1..arity]
vTVals = map (VarT . mkName) vVals
lVals = map (\i -> "l" <> show i) [1..arity]
lTVals = map (VarT . mkName) lVals
vectorTVals = zipWith AppT lTVals vTVals
numCxt = map (\i -> mkContext "Num" i) vectorTVals
foldCxt = map (\i -> mkContext "Foldable" i) lTVals
context = foldCxt ++ numCxt
nameE = VarE . mkName
#if MIN_VERSION_template_haskell(2,10,0)
mkContext c t = AppT (ConT (mkName c)) t
#else
mkContext c t = ClassP (mkName c) [t]
#endif
fieldDims' = ListE $ flip map vectorTVals
(\v -> nameE "getSum" `AppE`
(nameE "foldMap" `AppE`
(nameE "const" `AppE`
(ConE (mkName "Sum") `AppE` (LitE (IntegerL 1)))) `AppE`
(SigE (LitE (IntegerL 0)) v)))
fieldDimsFun = FunD (mkName "fieldDims")
[Clause [WildP]
(NormalB fieldDims') []]
in InstanceD context
(AppT (ConT (mkName "HasFieldDims")) recordType)
[fieldDimsFun]
class HasFieldSizes a where
fieldSizes :: a -> [Int]
return $ flip map [1..24] $ \arity ->
let typeName = mkName $ "Record" <> show arity
recordType = foldl (\a i -> AppT (AppT a (SigT (VarT (mkName ("n" <> show i))) (ConT ''Symbol)))
(VarT (mkName ("v" <> show i))))
(ConT typeName)
[1 .. arity]
vVals = map (\i -> "v" <> show i) [1..arity]
vTVals = map (VarT . mkName) vVals
#if MIN_VERSION_template_haskell(2,10,0)
mkContext c t = AppT (ConT (mkName c)) t
#else
mkContext c t = ClassP (mkName c) [t]
#endif
context = map (\v -> mkContext "Storable" v) vTVals
fieldSizes' = ListE $ flip map vTVals
(\v -> AppE (VarE (mkName "sizeOf"))
(SigE (VarE (mkName "undefined")) v))
fieldSizesFun = FunD (mkName "fieldSizes")
[Clause [WildP] (NormalB fieldSizes') []]
in InstanceD context
(AppT (ConT (mkName "HasFieldSizes")) recordType)
[fieldSizesFun]