grapefruit-records-0.1.0.0: src/Data/Record/Optionality.hs
{-|
This module provides support for optionality records.
Optionality records are used to specify interfaces with optional input data. Compared to an
ordinary record type, an optionality record type states for every field whether it is required
or optional. This is done by a slight abuse of field names. A field name @/name/@ is replaced by
either @'Req' /name/@ or @'Opt' /name/@. Optionality record types are never used directly in
types of actual values. Instead, they are converted into ordinary record types with the type
functions 'All' and 'Required'.
-}
module Data.Record.Optionality (
Req,
Opt,
OptRecord (type All, type Required)
) where
-- Data
import Data.Record as Record
-- |A marker for required fields.
data Req name
-- |A marker for optional fields.
data Opt name
-- |The class of all optionality record types.
class OptRecord (optRecord :: * -> *) where
{-|
Converts an optionality record type into an ordinary record type by dropping all 'Req'
and 'Opt' annotations.
-}
type All optRecord :: * -> *
{-|
Extracts all required fields from an optionality record type and drops their 'Req'
annotations.
-}
type Required optRecord :: * -> *
instance OptRecord X where
type All X = X
type Required X = X
instance (OptRecord optRecord) => OptRecord (optRecord :& Req name ::: sort) where
type All (optRecord :& Req name ::: sort) = All optRecord :& name ::: sort
type Required (optRecord :& Req name ::: sort) = Required optRecord :& name ::: sort
instance (OptRecord optRecord) => OptRecord (optRecord :& Opt name ::: sort) where
type All (optRecord :& Opt name ::: sort) = All optRecord :& name ::: sort
type Required (optRecord :& Opt name ::: sort) = Required optRecord