module Record.Aeson where
import BasePrelude
import Record.Types
import Record.Lens
import Data.Aeson.Types
import GHC.TypeLits
import Language.Haskell.TH
import Record.Aeson.TH
return $ do
arity <- [1 .. 24]
return $
let
recordName =
mkName $ showString "Record" $ show arity
arityNumbers =
enumFromTo 1 arity
fieldNameVarNames =
mkName . showString "n" . show <$> arityNumbers
valueVarNames =
mkName . showString "v" . show <$> arityNumbers
instanceDec =
InstanceD constraints headType decs
where
constraints =
knownSymbolConstraints <> toJSONConstraints
where
knownSymbolConstraints =
do
varName <- fieldNameVarNames
return $ mkClassP ''KnownSymbol [(VarT varName)]
toJSONConstraints =
do
varName <- valueVarNames
return $ mkClassP ''ToJSON [(VarT varName)]
headType =
AppT (ConT ''ToJSON) $
foldl' AppT (ConT recordName) $
map VarT $
interlace fieldNameVarNames valueVarNames
where
interlace a b = join (zipWith (\a b -> [a, b]) a b)
decs =
[toJSONDec]
where
toJSONDec =
FunD 'toJSON [clause]
where
clause =
Clause [pat] body []
where
pat =
ConP recordName varPats
where
varPats =
map VarP valueVarNames
body =
NormalB exp
where
exp =
AppE (VarE 'object) $ ListE $ do
(valueVarName, fieldNameVarName) <- zip valueVarNames fieldNameVarNames
let
labelExp =
AppE (VarE 'fromString) $
AppE (VarE 'symbolVal) $
SigE (VarE 'undefined) $
AppT (ConT ''FieldName) $
VarT fieldNameVarName
valueExp =
AppE (VarE 'toJSON) $
VarE valueVarName
return $ TupE $ [labelExp, valueExp]
in instanceDec