{-# LANGUAGE CPP, FlexibleInstances, IncoherentInstances, NamedFieldPuns,
NoImplicitPrelude, OverlappingInstances, TemplateHaskell,
UndecidableInstances #-}{-|
Module: Data.Aeson.TH
Copyright: (c) 2011, 2012 Bryan O'Sullivan
(c) 2011 MailRank, Inc.
License: Apache
Stability: experimental
Portability: portable
Functions to mechanically derive 'ToJSON' and 'FromJSON' instances. Note that
you need to enable the @TemplateHaskell@ language extension in order to use this
module.
An example shows how instances are generated for arbitrary data types. First we
define a data type:
@
data D a = Nullary
| Unary Int
| Product String Char a
| Record { testOne :: Double
, testTwo :: Bool
, testThree :: D a
} deriving Eq
@
Next we derive the necessary instances. Note that we make use of the
feature to change record field names. In this case we drop the first 4
characters of every field name. We also modify constructor names by
lower-casing them:
@
$('deriveJSON' 'defaultOptions'{'fieldLabelModifier' = 'drop' 4, 'constructorTagModifier' = map toLower} ''D)
@
Now we can use the newly created instances.
@
d :: D 'Int'
d = Record { testOne = 3.14159
, testTwo = 'True'
, testThree = Product \"test\" \'A\' 123
}
@
>>> fromJSON (toJSON d) == Success d
> True
Please note that you can derive instances for tuples using the following syntax:
@
-- FromJSON and ToJSON instances for 4-tuples.
$('deriveJSON' 'defaultOptions' ''(,,,))
@
-}moduleData.Aeson.TH(-- * Encoding configurationOptions(..),SumEncoding(..),defaultOptions,defaultTaggedObject-- * FromJSON and ToJSON derivation,deriveJSON,deriveToJSON,deriveFromJSON,mkToJSON,mkParseJSON)where---------------------------------------------------------------------------------- Imports---------------------------------------------------------------------------------- from aeson:importData.Aeson(toJSON,Object,object,(.=),(.:),(.:?),ToJSON,toJSON,FromJSON,parseJSON)importData.Aeson.Types(Value(..),Parser,Options(..),SumEncoding(..),defaultOptions,defaultTaggedObject)-- from base:importControl.Applicative(pure,(<$>),(<*>))importControl.Monad(return,mapM,liftM2,fail)importData.Bool(Bool(False,True),otherwise,(&&))importData.Eq((==))importData.Function(($),(.))importData.Functor(fmap)importData.Int(Int)importData.Either(Either(Left,Right))importData.List((++),foldl,foldl',intercalate,length,map,zip,genericLength,all,partition)importData.Maybe(Maybe(Nothing,Just),catMaybes)importPrelude(String,(-),Integer,fromIntegral,error)importText.Printf(printf)importText.Show(show)#if __GLASGOW_HASKELL__ < 700importControl.Monad((>>=),(>>))importPrelude(fromInteger)#endif-- from unordered-containers:importqualifiedData.HashMap.StrictasH(lookup,toList)-- from template-haskell:importLanguage.Haskell.THimportLanguage.Haskell.TH.Syntax(VarStrictType)-- from text:importqualifiedData.TextasT(Text,pack,unpack)-- from vector:importqualifiedData.VectorasV(unsafeIndex,null,length,create,fromList)importqualifiedData.Vector.MutableasVM(unsafeNew,unsafeWrite)---------------------------------------------------------------------------------- Convenience---------------------------------------------------------------------------------- | Generates both 'ToJSON' and 'FromJSON' instance declarations for the given-- data type.---- This is a convienience function which is equivalent to calling both-- 'deriveToJSON' and 'deriveFromJSON'.deriveJSON::Options-- ^ Encoding options.->Name-- ^ Name of the type for which to generate 'ToJSON' and 'FromJSON'-- instances.->Q[Dec]deriveJSONoptsname=liftM2(++)(deriveToJSONoptsname)(deriveFromJSONoptsname)---------------------------------------------------------------------------------- ToJSON--------------------------------------------------------------------------------{-
TODO: Don't constrain phantom type variables.
data Foo a = Foo Int
instance (ToJSON a) ⇒ ToJSON Foo where ...
The above (ToJSON a) constraint is not necessary and perhaps undesirable.
-}-- | Generates a 'ToJSON' instance declaration for the given data type.deriveToJSON::Options-- ^ Encoding options.->Name-- ^ Name of the type for which to generate a 'ToJSON' instance-- declaration.->Q[Dec]deriveToJSONoptsname=withTypename$\tvbscons->fmap(:[])$fromConstvbsconswherefromCons::[TyVarBndr]->[Con]->QDecfromConstvbscons=instanceD(return$map(\t->ClassP''ToJSON[VarTt])typeNames)(classType`appT`instanceType)[funD'toJSON[clause[](normalB$consToJSONoptscons)[]]]whereclassType=conT''ToJSONtypeNames=maptvbNametvbsinstanceType=foldl'appT(conTname)$mapvarTtypeNames-- | Generates a lambda expression which encodes the given data type as JSON.mkToJSON::Options-- ^ Encoding options.->Name-- ^ Name of the type to encode.->QExpmkToJSONoptsname=withTypename(\_cons->consToJSONoptscons)-- | Helper function used by both 'deriveToJSON' and 'mkToJSON'. Generates code-- to generate the JSON encoding of a number of constructors. All constructors-- must be from the same type.consToJSON::Options-- ^ Encoding options.->[Con]-- ^ Constructors for which to generate JSON generating code.->QExpconsToJSON_[]=error$"Data.Aeson.TH.consToJSON: "++"Not a single constructor given!"-- A single constructor is directly encoded. The constructor itself may be-- forgotten.consToJSONopts[con]=dovalue<-newName"value"lam1E(varPvalue)$caseE(varEvalue)[encodeArgsoptsFalsecon]consToJSONoptscons=dovalue<-newName"value"lam1E(varPvalue)$caseE(varEvalue)matcheswherematches|allNullaryToStringTagopts&&allisNullarycons=[match(conPconName[])(normalB$conStroptsconName)[]|con<-cons,letconName=getConNamecon]|otherwise=[encodeArgsoptsTruecon|con<-cons]conStr::Options->Name->QExpconStropts=appE[|String|].conTxtoptsconTxt::Options->Name->QExpconTxtopts=appE[|T.pack|].conStringEoptsconStringE::Options->Name->QExpconStringEopts=stringE.constructorTagModifieropts.nameBase-- | If constructor is nullary.isNullary::Con->BoolisNullary(NormalC_[])=TrueisNullary_=FalseencodeSum::Options->Bool->Name->QExp->QExpencodeSumoptsmultiConsconNameexp|multiCons=casesumEncodingoptsofTwoElemArray->[|Array|]`appE`([|V.fromList|]`appE`listE[conStroptsconName,exp])TaggedObject{tagFieldName,contentsFieldName}->[|object|]`appE`listE[infixApp[|T.packtagFieldName|][|(.=)|](conStroptsconName),infixApp[|T.packcontentsFieldName|][|(.=)|]exp]ObjectWithSingleField->[|object|]`appE`listE[infixApp(conTxtoptsconName)[|(.=)|]exp]|otherwise=exp-- | Generates code to generate the JSON encoding of a single constructor.encodeArgs::Options->Bool->Con->QMatch-- Nullary constructors. Generates code that explicitly matches against the-- constructor even though it doesn't contain data. This is useful to prevent-- type errors.encodeArgsoptsmultiCons(NormalCconName[])=match(conPconName[])(normalB(encodeSumoptsmultiConsconName[e|toJSON([]::[()])|]))[]-- Polyadic constructors with special case for unary constructors.encodeArgsoptsmultiCons(NormalCconNamets)=doletlen=lengthtsargs<-mapMnewName["arg"++shown|n<-[1..len]]js<-case[[|toJSON|]`appE`varEarg|arg<-args]of-- Single argument is directly converted.[e]->returne-- Multiple arguments are converted to a JSON array.es->domv<-newName"mv"letnewMV=bindS(varPmv)([|VM.unsafeNew|]`appE`litE(integerL$fromIntegrallen))stmts=[noBindS$[|VM.unsafeWrite|]`appE`(varEmv)`appE`litE(integerLix)`appE`e|(ix,e)<-zip[(0::Integer)..]es]ret=noBindS$[|return|]`appE`varEmvreturn$[|Array|]`appE`(varE'V.create`appE`doE(newMV:stmts++[ret]))match(conPconName$mapvarPargs)(normalB$encodeSumoptsmultiConsconNamejs)[]-- Records.encodeArgsoptsmultiCons(RecCconNamets)=doargs<-mapMnewName["arg"++shown|(_,n)<-zipts[1::Integer..]]letexp=[|object|]`appE`pairspairs|omitNothingFieldsopts=infixAppmaybeFields[|(++)|]restFields|otherwise=listE$maptoPairargConsargCons=zipargstsmaybeFields=[|catMaybes|]`appE`listE(mapmaybeToPairmaybes)restFields=listE$maptoPairrest(maybes,rest)=partitionisMaybeargConsisMaybe(_,(_,_,AppT(ConTt)_))=t==''MaybeisMaybe_=FalsemaybeToPair(arg,(field,_,_))=infixApp(infixE(Just$toFieldNamefield)[|(.=)|]Nothing)[|(<$>)|](varEarg)toPair(arg,(field,_,_))=infixApp(toFieldNamefield)[|(.=)|](varEarg)toFieldNamefield=[|T.pack|]`appE`fieldLabelExpoptsfieldmatch(conPconName$mapvarPargs)(normalB$ifmultiConsthencasesumEncodingoptsofTwoElemArray->[|toJSON|]`appE`tupE[conStroptsconName,exp]TaggedObject{tagFieldName}->[|object|]`appE`-- TODO: Maybe throw an error in case-- tagFieldName overwrites a field in pairs.infixApp(infixApp[|T.packtagFieldName|][|(.=)|](conStroptsconName))[|(:)|]pairsObjectWithSingleField->[|object|]`appE`listE[infixApp(conTxtoptsconName)[|(.=)|]exp]elseexp)[]-- Infix constructors.encodeArgsoptsmultiCons(InfixC_conName_)=doal<-newName"argL"ar<-newName"argR"match(infixP(varPal)conName(varPar))(normalB$encodeSumoptsmultiConsconName$[|toJSON|]`appE`listE[[|toJSON|]`appE`varEa|a<-[al,ar]])[]-- Existentially quantified constructors.encodeArgsoptsmultiCons(ForallC__con)=encodeArgsoptsmultiConscon---------------------------------------------------------------------------------- FromJSON---------------------------------------------------------------------------------- | Generates a 'FromJSON' instance declaration for the given data type.deriveFromJSON::Options-- ^ Encoding options.->Name-- ^ Name of the type for which to generate a 'FromJSON' instance-- declaration.->Q[Dec]deriveFromJSONoptsname=withTypename$\tvbscons->fmap(:[])$fromConstvbsconswherefromCons::[TyVarBndr]->[Con]->QDecfromConstvbscons=instanceD(return$map(\t->ClassP''FromJSON[VarTt])typeNames)(classType`appT`instanceType)[funD'parseJSON[clause[](normalB$consFromJSONnameoptscons)[]]]whereclassType=conT''FromJSONtypeNames=maptvbNametvbsinstanceType=foldl'appT(conTname)$mapvarTtypeNames-- | Generates a lambda expression which parses the JSON encoding of the given-- data type.mkParseJSON::Options-- ^ Encoding options.->Name-- ^ Name of the encoded type.->QExpmkParseJSONoptsname=withTypename(\_cons->consFromJSONnameoptscons)-- | Helper function used by both 'deriveFromJSON' and 'mkParseJSON'. Generates-- code to parse the JSON encoding of a number of constructors. All constructors-- must be from the same type.consFromJSON::Name-- ^ Name of the type to which the constructors belong.->Options-- ^ Encoding options->[Con]-- ^ Constructors for which to generate JSON parsing code.->QExpconsFromJSON__[]=error$"Data.Aeson.TH.consFromJSON: "++"Not a single constructor given!"consFromJSONtNameopts[con]=dovalue<-newName"value"lam1E(varPvalue)(parseArgstNameoptscon(Rightvalue))consFromJSONtNameoptscons=dovalue<-newName"value"lam1E(varPvalue)$caseE(varEvalue)$ifallNullaryToStringTagopts&&allisNullaryconsthenallNullaryMatcheselsemixedMatcheswhereallNullaryMatches=[dotxt<-newName"txt"match(conP'String[varPtxt])(guardedB$[liftM2(,)(normalG$infixApp(varEtxt)[|(==)|]([|T.pack|]`appE`conStringEoptsconName))([|pure|]`appE`conEconName)|con<-cons,letconName=getConNamecon]++[liftM2(,)(normalG[|otherwise|])([|noMatchFail|]`appE`(litE$stringL$showtName)`appE`([|T.unpack|]`appE`varEtxt))])[],doother<-newName"other"match(varPother)(normalB$[|noStringFail|]`appE`(litE$stringL$showtName)`appE`([|valueConName|]`appE`varEother))[]]mixedMatches=casesumEncodingoptsofTaggedObject{tagFieldName,contentsFieldName}->parseObject$parseTaggedObjecttagFieldNamecontentsFieldNameObjectWithSingleField->parseObject$parseObjectWithSingleFieldTwoElemArray->[doarr<-newName"array"match(conP'Array[varParr])(guardedB$[liftM2(,)(normalG$infixApp([|V.length|]`appE`varEarr)[|(==)|](litE$integerL2))(parse2ElemArrayarr),liftM2(,)(normalG[|otherwise|])(([|not2ElemArray|]`appE`(litE$stringL$showtName)`appE`([|V.length|]`appE`varEarr)))])[],doother<-newName"other"match(varPother)(normalB$[|noArrayFail|]`appE`(litE$stringL$showtName)`appE`([|valueConName|]`appE`varEother))[]]parseObjectf=[doobj<-newName"obj"match(conP'Object[varPobj])(normalB$fobj)[],doother<-newName"other"match(varPother)(normalB$[|noObjectFail|]`appE`(litE$stringL$showtName)`appE`([|valueConName|]`appE`varEother))[]]parseTaggedObjecttypFieldNamevalFieldNameobj=doconKey<-newName"conKey"doE[bindS(varPconKey)(infixApp(varEobj)[|(.:)|]([|T.pack|]`appE`stringEtypFieldName)),noBindS$parseContentsconKey(Left(valFieldName,obj))'conNotFoundFailTaggedObject]parse2ElemArrayarr=doconKey<-newName"conKey"conVal<-newName"conVal"letletIxnix=valD(varPn)(normalB([|V.unsafeIndex|]`appE`varEarr`appE`litE(integerLix)))[]letE[letIxconKey0,letIxconVal1](caseE(varEconKey)[dotxt<-newName"txt"match(conP'String[varPtxt])(normalB$parseContentstxt(RightconVal)'conNotFoundFail2ElemArray)[],doother<-newName"other"match(varPother)(normalB$[|firstElemNoStringFail|]`appE`(litE$stringL$showtName)`appE`([|valueConName|]`appE`varEother))[]])parseObjectWithSingleFieldobj=doconKey<-newName"conKey"conVal<-newName"conVal"caseE([e|H.toList|]`appE`varEobj)[match(listP[tupP[varPconKey,varPconVal]])(normalB$parseContentsconKey(RightconVal)'conNotFoundFailObjectSingleField)[],doother<-newName"other"match(varPother)(normalB$[|wrongPairCountFail|]`appE`(litE$stringL$showtName)`appE`([|show.length|]`appE`varEother))[]]parseContentsconKeycontentserrorFun=caseE(varEconKey)[matchwildP(guardedB$[dog<-normalG$infixApp(varEconKey)[|(==)|]([|T.pack|]`appE`conNameExpoptscon)e<-parseArgstNameoptsconcontentsreturn(g,e)|con<-cons]++[liftM2(,)(normalG[e|otherwise|])(varEerrorFun`appE`(litE$stringL$showtName)`appE`listE(map(litE.stringL.constructorTagModifieropts.nameBase.getConName)cons)`appE`([|T.unpack|]`appE`varEconKey))])[]]parseNullaryMatches::Name->Name->[QMatch]parseNullaryMatchestNameconName=[doarr<-newName"arr"match(conP'Array[varParr])(guardedB$[liftM2(,)(normalG$[|V.null|]`appE`varEarr)([|pure|]`appE`conEconName),liftM2(,)(normalG[|otherwise|])(parseTypeMismatchtNameconName(litE$stringL"an empty Array")(infixApp(litE$stringL$"Array of length ")[|(++)|]([|show.V.length|]`appE`varEarr)))])[],matchFailedtNameconName"Array"]parseUnaryMatches::Name->[QMatch]parseUnaryMatchesconName=[doarg<-newName"arg"match(varParg)(normalB$infixApp(conEconName)[|(<$>)|]([|parseJSON|]`appE`varEarg))[]]parseRecord::Options->Name->Name->[VarStrictType]->Name->ExpQparseRecordoptstNameconNametsobj=foldl'(\ab->infixAppa[|(<*>)|]b)(infixApp(conEconName)[|(<$>)|]x)xswherex:xs=[[|lookupField|]`appE`(litE$stringL$showtName)`appE`(litE$stringL$constructorTagModifieropts$nameBaseconName)`appE`(varEobj)`appE`([|T.pack|]`appE`fieldLabelExpoptsfield)|(field,_,_)<-ts]getValField::Name->String->[MatchQ]->QExpgetValFieldobjvalFieldNamematches=doval<-newName"val"doE[bindS(varPval)$infixApp(varEobj)[|(.:)|]([|T.pack|]`appE`(litE$stringLvalFieldName)),noBindS$caseE(varEval)matches]-- | Generates code to parse the JSON encoding of a single constructor.parseArgs::Name-- ^ Name of the type to which the constructor belongs.->Options-- ^ Encoding options.->Con-- ^ Constructor for which to generate JSON parsing code.->Either(String,Name)Name-- ^ Left (valFieldName, objName) or-- Right valName->QExp-- Nullary constructors.parseArgstName_(NormalCconName[])(Left(valFieldName,obj))=getValFieldobjvalFieldName$parseNullaryMatchestNameconNameparseArgstName_(NormalCconName[])(RightvalName)=caseE(varEvalName)$parseNullaryMatchestNameconName-- Unary constructors.parseArgs__(NormalCconName[_])(Left(valFieldName,obj))=getValFieldobjvalFieldName$parseUnaryMatchesconNameparseArgs__(NormalCconName[_])(RightvalName)=caseE(varEvalName)$parseUnaryMatchesconName-- Polyadic constructors.parseArgstName_(NormalCconNamets)(Left(valFieldName,obj))=getValFieldobjvalFieldName$parseProducttNameconName$genericLengthtsparseArgstName_(NormalCconNamets)(RightvalName)=caseE(varEvalName)$parseProducttNameconName$genericLengthts-- Records.parseArgstNameopts(RecCconNamets)(Left(_,obj))=parseRecordoptstNameconNametsobjparseArgstNameopts(RecCconNamets)(RightvalName)=doobj<-newName"recObj"caseE(varEvalName)[match(conP'Object[varPobj])(normalB$parseRecordoptstNameconNametsobj)[],matchFailedtNameconName"Object"]-- Infix constructors. Apart from syntax these are the same as-- polyadic constructors.parseArgstName_(InfixC_conName_)(Left(valFieldName,obj))=getValFieldobjvalFieldName$parseProducttNameconName2parseArgstName_(InfixC_conName_)(RightvalName)=caseE(varEvalName)$parseProducttNameconName2-- Existentially quantified constructors. We ignore the quantifiers-- and proceed with the contained constructor.parseArgstNameopts(ForallC__con)contents=parseArgstNameoptsconcontents-- | Generates code to parse the JSON encoding of an n-ary-- constructor.parseProduct::Name-- ^ Name of the type to which the constructor belongs.->Name-- ^ 'Con'structor name.->Integer-- ^ 'Con'structor arity.->[QMatch]parseProducttNameconNamenumArgs=[doarr<-newName"arr"-- List of: "parseJSON (arr `V.unsafeIndex` <IX>)"letx:xs=[[|parseJSON|]`appE`infixApp(varEarr)[|V.unsafeIndex|](litE$integerLix)|ix<-[0..numArgs-1]]match(conP'Array[varParr])(normalB$condE(infixApp([|V.length|]`appE`varEarr)[|(==)|](litE$integerLnumArgs))(foldl'(\ab->infixAppa[|(<*>)|]b)(infixApp(conEconName)[|(<$>)|]x)xs)(parseTypeMismatchtNameconName(litE$stringL$"Array of length "++shownumArgs)(infixApp(litE$stringL$"Array of length ")[|(++)|]([|show.V.length|]`appE`varEarr))))[],matchFailedtNameconName"Array"]---------------------------------------------------------------------------------- Parsing errors--------------------------------------------------------------------------------matchFailed::Name->Name->String->MatchQmatchFailedtNameconNameexpected=doother<-newName"other"match(varPother)(normalB$parseTypeMismatchtNameconName(litE$stringLexpected)([|valueConName|]`appE`varEother))[]parseTypeMismatch::Name->Name->ExpQ->ExpQ->ExpQparseTypeMismatchtNameconNameexpectedactual=foldlappE[|parseTypeMismatch'|][litE$stringL$nameBaseconName,litE$stringL$showtName,expected,actual]class(FromJSONa)=>LookupFieldawherelookupField::String->String->Object->T.Text->Parserainstance(FromJSONa)=>LookupFieldawherelookupFieldtNamerecobjkey=caseH.lookupkeyobjofNothing->unknownFieldFailtNamerec(T.unpackkey)Justv->parseJSONvinstance(FromJSONa)=>LookupField(Maybea)wherelookupField__=(.:?)unknownFieldFail::String->String->String->ParserfailunknownFieldFailtNamereckey=fail$printf"When parsing the record %s of type %s the key %s was not present."rectNamekeynoArrayFail::String->String->ParserfailnoArrayFailto=fail$printf"When parsing %s expected Array but got %s."tonoObjectFail::String->String->ParserfailnoObjectFailto=fail$printf"When parsing %s expected Object but got %s."tofirstElemNoStringFail::String->String->ParserfailfirstElemNoStringFailto=fail$printf"When parsing %s expected an Array of 2 elements where the first element is a String but got %s at the first element."towrongPairCountFail::String->String->ParserfailwrongPairCountFailtn=fail$printf"When parsing %s expected an Object with a single tag/contents pair but got %s pairs."tnnoStringFail::String->String->ParserfailnoStringFailto=fail$printf"When parsing %s expected String but got %s."tonoMatchFail::String->String->ParserfailnoMatchFailto=fail$printf"When parsing %s expected a String with the tag of a constructor but got %s."tonot2ElemArray::String->Int->Parserfailnot2ElemArrayti=fail$printf"When parsing %s expected an Array of 2 elements but got %i elements"ticonNotFoundFail2ElemArray::String->[String]->String->ParserfailconNotFoundFail2ElemArraytcso=fail$printf"When parsing %s expected a 2-element Array with a tag and contents element where the tag is one of [%s], but got %s."t(intercalate", "cs)oconNotFoundFailObjectSingleField::String->[String]->String->ParserfailconNotFoundFailObjectSingleFieldtcso=fail$printf"When parsing %s expected an Object with a single tag/contents pair where the tag is one of [%s], but got %s."t(intercalate", "cs)oconNotFoundFailTaggedObject::String->[String]->String->ParserfailconNotFoundFailTaggedObjecttcso=fail$printf"When parsing %s expected an Object with a tag field where the value is one of [%s], but got %s."t(intercalate", "cs)oparseTypeMismatch'::String->String->String->String->ParserfailparseTypeMismatch'tNameconNameexpectedactual=fail$printf"When parsing the constructor %s of type %s expected %s but got %s."conNametNameexpectedactual---------------------------------------------------------------------------------- Utility functions---------------------------------------------------------------------------------- | Boilerplate for top level splices.---- The given 'Name' must be from a type constructor. Furthermore, the-- type constructor must be either a data type or a newtype. Any other-- value will result in an exception.withType::Name->([TyVarBndr]->[Con]->Qa)-- ^ Function that generates the actual code. Will be applied-- to the type variable binders and constructors extracted-- from the given 'Name'.->Qa-- ^ Resulting value in the 'Q'uasi monad.withTypenamef=doinfo<-reifynamecaseinfoofTyConIdec->casedecofDataD__tvbscons_->ftvbsconsNewtypeD__tvbscon_->ftvbs[con]other->error$"Data.Aeson.TH.withType: Unsupported type: "++showother_->error"Data.Aeson.TH.withType: I need the name of a type."-- | Extracts the name from a constructor.getConName::Con->NamegetConName(NormalCname_)=namegetConName(RecCname_)=namegetConName(InfixC_name_)=namegetConName(ForallC__con)=getConNamecon-- | Extracts the name from a type variable binder.tvbName::TyVarBndr->NametvbName(PlainTVname)=nametvbName(KindedTVname_)=name-- | Makes a string literal expression from a constructor's name.conNameExp::Options->Con->QExpconNameExpopts=litE.stringL.constructorTagModifieropts.nameBase.getConName-- | Creates a string literal expression from a record field label.fieldLabelExp::Options-- ^ Encoding options->Name->QExpfieldLabelExpopts=litE.stringL.fieldLabelModifieropts.nameBase-- | The name of the outermost 'Value' constructor.valueConName::Value->StringvalueConName(Object_)="Object"valueConName(Array_)="Array"valueConName(String_)="String"valueConName(Number_)="Number"valueConName(Bool_)="Boolean"valueConNameNull="Null"