records-sop- Record subtyping and record utilities with generics-sop

Safe HaskellNone




A suitable representation for single-constructor records

type FieldLabel = Symbol Source #

On the type-level, we represent fiel labels using symbols.

type RecordCode = [(FieldLabel, Type)] Source #

The record code deviates from the normal SOP code in two ways:

  • There is only one list, because we require that there is only a single constructor.
  • In addition to the types of the fields, we store the labels of the fields.

type Record r = NP P r Source #

The representation of a record is just a product indexed by a record code, containing elements of the types indicated by the code.

Note that the representation is deliberately chosen such that it has the same run-time representation as the product part of the normal SOP representation.

type RecordRep a = Record (RecordCodeOf a) Source #

The record representation of a type is a record indexed by the record code.

Computing the record code

type RecordCodeOf a = ToRecordCode_Datatype a (DatatypeInfoOf a) (Code a) Source #

This type-level function takes the type-level metadata provided by generics-sop as well as the normal generics-sop code, and transforms them into the record code.

Arguably, the record code is more usable than the representation directly on offer by generics-sop. So it's worth asking whether this representation should be included in generics-sop ...

The function will only reduce if the argument type actually is a record, meaning it must have exactly one constructor, and that constructor must have field labels attached to it.

type IsRecord a r = IsRecord' a r (GetSingleton (Code a)) Source #

The constraint IsRecord a r states that the type a is a record type (i.e., has exactly one constructor and field labels) and that r is the record code associated with a.

type ValidRecordCode r xs = (ExtractTypesFromRecordCode r ~ xs, RecombineRecordCode (ExtractLabelsFromRecordCode r) xs ~ r) Source #

Relates a recordcode r and a list of types xs, stating that xs is indeed the list of types contained in r.

type family ExtractTypesFromRecordCode (r :: RecordCode) :: [Type] where ... Source #

Extracts all the types from a record code.

type family ExtractLabelsFromRecordCode (r :: RecordCode) :: [FieldLabel] where ... Source #

Extracts all the field labels from a record code.

type family RecombineRecordCode (ls :: [FieldLabel]) (ts :: [Type]) :: RecordCode where ... Source #

Given a list of labels and types, recombines them into a record code.

An important aspect of this function is that it is defined by induction on the list of types, and forces the list of field labels to be at least as long.


RecombineRecordCode _ '[] = '[] 
RecombineRecordCode ls (t ': ts) = '(Head ls, t) ': RecombineRecordCode (Tail ls) ts 

Conversion between a type and its record representation.

toRecord :: IsRecord a _r => a -> RecordRep a Source #

Convert a value into its record representation.

fromRecord :: IsRecord a r => RecordRep a -> a Source #

Convert a record representation back into a value.


newtype P p Source #

Projection of the second component of a type-level pair, wrapped in a newtype.


P (Snd p) 


Eq a1 => Eq (P a ((,) a * l a1)) Source # 


(==) :: P a ((a, *) l a1) -> P a ((a, *) l a1) -> Bool #

(/=) :: P a ((a, *) l a1) -> P a ((a, *) l a1) -> Bool #

Ord a1 => Ord (P a ((,) a * l a1)) Source # 


compare :: P a ((a, *) l a1) -> P a ((a, *) l a1) -> Ordering #

(<) :: P a ((a, *) l a1) -> P a ((a, *) l a1) -> Bool #

(<=) :: P a ((a, *) l a1) -> P a ((a, *) l a1) -> Bool #

(>) :: P a ((a, *) l a1) -> P a ((a, *) l a1) -> Bool #

(>=) :: P a ((a, *) l a1) -> P a ((a, *) l a1) -> Bool #

max :: P a ((a, *) l a1) -> P a ((a, *) l a1) -> P a ((a, *) l a1) #

min :: P a ((a, *) l a1) -> P a ((a, *) l a1) -> P a ((a, *) l a1) #

Show a1 => Show (P a ((,) a * l a1)) Source # 


showsPrec :: Int -> P a ((a, *) l a1) -> ShowS #

show :: P a ((a, *) l a1) -> String #

showList :: [P a ((a, *) l a1)] -> ShowS #

Generic (P a p) Source # 

Associated Types

type Rep (P a p) :: * -> * #


from :: P a p -> Rep (P a p) x #

to :: Rep (P a p) x -> P a p #

NFData a1 => NFData (P a ((,) a * l a1)) Source # 


rnf :: P a ((a, *) l a1) -> () #

type Rep (P a p) Source # 
type Rep (P a p) = D1 (MetaData "P" "Generics.SOP.Record" "records-sop-" True) (C1 (MetaCons "P" PrefixI False) (S1 (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (Snd a Type p))))

type family Snd (p :: (a, b)) :: b where ... Source #

Type-level variant of snd.


Snd '(a, b) = b