Skip to content

Deriving instances

wireform provides two ways to derive encode/decode instances for your types.

Each format ships a Derive module with a TH splice that reads ANN pragmas from the shared wireform-derive annotation vocabulary. This is the only path that supports field renaming, tagging, skipping, and backend-specific overrides:

{-# LANGUAGE TemplateHaskell #-}
import Wireform.Derive (renameStyle, SnakeCase)
import MsgPack.Derive (deriveMsgPack)
import CBOR.Derive (deriveCBOR)
data User = User
{ userName :: !Text
, userAge :: !Int
, userRole :: !Text
}
{-# ANN type User (renameStyle SnakeCase) #-}
deriveMsgPack ''User
deriveCBOR ''User

Both formats see user_name, user_age, and user_role on the wire, driven by the same annotation.

Every format’s typeclass has DefaultSignatures that delegate to GHC.Generics. If you don’t need any customization, write empty instance declarations:

{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics (Generic)
import MsgPack.Class (ToMsgPack, FromMsgPack)
data User = User
{ userName :: !Text
, userAge :: !Int
} deriving stock (Show, Eq, Generic)
instance ToMsgPack User
instance FromMsgPack User

Field names go to the wire verbatim. The wireform-derive annotation vocabulary has no effect on this path.

See wireform-derive for the complete annotation vocabulary: rename, renameStyle, tag, skip, flatten, defaults, optional, required, coerced, wireOverride, forBackend, and extension.

FormatTH deriverModule
MessagePackderiveMsgPackMsgPack.Derive
CBORderiveCBORCBOR.Derive
YAMLderiveYAMLYAML.Derive
TOMLderiveTOMLTOML.Derive
XMLderiveXMLXML.Derive
HTMLderiveHTMLHTML.Derive
BSONderiveBSONBSON.Derive
IonderiveIonIon.Derive
EDNderiveEDNEDN.Derive
BencodederiveBencodeBencode.Derive
CSVderiveCSVCSV.Derive
ForyderiveForyFory.Derive
ThriftderiveThriftThrift.Derive
AvroderiveAvroAvro.Derive
BondderiveBondBond.Derive
FlatBuffersderiveFlatBuffersFlatBuffers.Derive
Cap’n ProtoderiveCapnProtoCapnProto.Derive
ASN.1deriveASN1ASN1.Derive
Aeson (JSON)deriveJSONWireform.Derive.Aeson