ruin-0.1.0.1: Pliable records

Safe HaskellNone
LanguageHaskell2010

Data.Ruin.Core

Contents

Description

The core subset of the libary interface. Data.Ruin offers more.

The basic idea of this module is that anonymous records are only used to emulate named function arguments. Thus, this module provides very little in the way of creating records; it expects that you'll declare and build your record types as usual.

The most solid use case for this module is a data type for parsing the command-line.

Step 1
Define a record type for each command.
Step 2
Define a sum type where each constructor contains only the corresponding command record type.
Step 3
Define a command-line parser for each record type using rtoA.
Step 4
Combine those parser using rupA.

Synopsis

Records

data s :@ a infix 1 Source #

A record type with a single field.

Instances

(~) Symbol s1 s2 => Has s1 ((:@) s2 a) Source # 

Associated Types

type FieldType (s1 :: Symbol) ((:@) s2 a) :: * Source #

Methods

extricate1 :: Label s1 -> (s2 :@ a) -> Eval (FieldType s1 (s2 :@ a)) Source #

Functor ((:@) s) Source # 

Methods

fmap :: (a -> b) -> (s :@ a) -> s :@ b #

(<$) :: a -> (s :@ b) -> s :@ a #

Generic1 ((:@) s) Source # 

Associated Types

type Rep1 ((:@) s :: * -> *) :: * -> * #

Methods

from1 :: (s :@ a) -> Rep1 ((:@) s) a #

to1 :: Rep1 ((:@) s) a -> s :@ a #

Eq a => Eq ((:@) s a) Source # 

Methods

(==) :: (s :@ a) -> (s :@ a) -> Bool #

(/=) :: (s :@ a) -> (s :@ a) -> Bool #

(Data a, KnownSymbol s) => Data ((:@) s a) Source # 

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> (s :@ a) -> c (s :@ a) #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (s :@ a) #

toConstr :: (s :@ a) -> Constr #

dataTypeOf :: (s :@ a) -> DataType #

dataCast1 :: Typeable (* -> *) t => (forall d. Data d => c (t d)) -> Maybe (c (s :@ a)) #

dataCast2 :: Typeable (* -> * -> *) t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (s :@ a)) #

gmapT :: (forall b. Data b => b -> b) -> (s :@ a) -> s :@ a #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> (s :@ a) -> r #

gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> (s :@ a) -> r #

gmapQ :: (forall d. Data d => d -> u) -> (s :@ a) -> [u] #

gmapQi :: Int -> (forall d. Data d => d -> u) -> (s :@ a) -> u #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> (s :@ a) -> m (s :@ a) #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> (s :@ a) -> m (s :@ a) #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> (s :@ a) -> m (s :@ a) #

Ord a => Ord ((:@) s a) Source # 

Methods

compare :: (s :@ a) -> (s :@ a) -> Ordering #

(<) :: (s :@ a) -> (s :@ a) -> Bool #

(<=) :: (s :@ a) -> (s :@ a) -> Bool #

(>) :: (s :@ a) -> (s :@ a) -> Bool #

(>=) :: (s :@ a) -> (s :@ a) -> Bool #

max :: (s :@ a) -> (s :@ a) -> s :@ a #

min :: (s :@ a) -> (s :@ a) -> s :@ a #

(KnownSymbol s, Show a) => Show ((:@) s a) Source # 

Methods

showsPrec :: Int -> (s :@ a) -> ShowS #

show :: (s :@ a) -> String #

showList :: [s :@ a] -> ShowS #

Generic ((:@) s a) Source # 

Associated Types

type Rep ((:@) s a) :: * -> * #

Methods

from :: (s :@ a) -> Rep (s :@ a) x #

to :: Rep (s :@ a) x -> s :@ a #

(Lift a, KnownSymbol s) => Lift ((:@) s a) Source # 

Methods

lift :: (s :@ a) -> Q Exp #

Binary a => Binary ((:@) s a) Source # 

Methods

put :: (s :@ a) -> Put #

get :: Get (s :@ a) #

putList :: [s :@ a] -> Put #

Serialize a => Serialize ((:@) s a) Source # 

Methods

put :: Putter (s :@ a) #

get :: Get (s :@ a) #

NFData a => NFData ((:@) s a) Source # 

Methods

rnf :: (s :@ a) -> () #

Build ((:@) s a) Source # 

Associated Types

type Fields ((:@) s a) :: [(Symbol, *)] Source #

type Shape ((:@) s a) o :: Constraint Source #

Methods

build :: (Applicative i, GivesThese (Fields (s :@ a)) i rc) => rc -> Compose * * Eval i (s :@ a) Source #

buildNonStrict :: GivesThese (Fields (s :@ a)) Identity rc => rc -> s :@ a Source #

type FieldType s1 ((:@) s2 a) Source # 
type FieldType s1 ((:@) s2 a) = a
type Rep1 ((:@) s) Source # 
type Rep1 ((:@) s) = D1 (MetaData ":@" "Data.Ruin.All" "ruin-0.1.0.1-1nMKf3bIpLD7vK6e2S9ClO" True) (C1 (MetaCons "Dub" PrefixI False) (S1 (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) Par1))
type Rep ((:@) s a) Source # 
type Rep ((:@) s a) = D1 (MetaData ":@" "Data.Ruin.All" "ruin-0.1.0.1-1nMKf3bIpLD7vK6e2S9ClO" True) (C1 (MetaCons "Dub" PrefixI False) (S1 (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 a)))
type Fields ((:@) s a) Source # 
type Fields ((:@) s a) = (:) (Symbol, *) ((,) Symbol * s a) ([] (Symbol, *))
type Shape ((:@) s _) o Source # 
type Shape ((:@) s _) o = Hoid * (* -> *) ((:@) s) o

dub :: Label s -> a -> s :@ a Source #

undub :: Label s -> (s :@ a) -> a Source #

Accessing parts of records

rpat :: QuasiQuoter Source #

rpat is like rna, but it only works for patterns.

Building records

class Build t Source #

Record types: product types where each factor has a static name (i.e. the Fields).

Minimal complete definition

build

Instances

Build () Source # 

Associated Types

type Fields () :: [(Symbol, *)] Source #

type Shape () o :: Constraint Source #

Methods

build :: (Applicative i, GivesThese (Fields ()) i rc) => rc -> Compose * * Eval i () Source #

buildNonStrict :: GivesThese (Fields ()) Identity rc => rc -> () Source #

Build a => Build (Tup1 a) Source # 

Associated Types

type Fields (Tup1 a) :: [(Symbol, *)] Source #

type Shape (Tup1 a) o :: Constraint Source #

Methods

build :: (Applicative i, GivesThese (Fields (Tup1 a)) i rc) => rc -> Compose * * Eval i (Tup1 a) Source #

buildNonStrict :: GivesThese (Fields (Tup1 a)) Identity rc => rc -> Tup1 a Source #

(KnownFD fd, Hoid FD ([(Symbol, *)] -> FD) MkFD fd) => Build (R fd) Source # 

Associated Types

type Fields (R fd) :: [(Symbol, *)] Source #

type Shape (R fd) o :: Constraint Source #

Methods

build :: (Applicative i, GivesThese (Fields (R fd)) i rc) => rc -> Compose * * Eval i (R fd) Source #

buildNonStrict :: GivesThese (Fields (R fd)) Identity rc => rc -> R fd Source #

TypeError Constraint (NoFun (* -> Constraint) Build) => Build (a -> b) Source #

This is a non-instance.

Associated Types

type Fields (a -> b) :: [(Symbol, *)] Source #

type Shape (a -> b) o :: Constraint Source #

Methods

build :: (Applicative i, GivesThese (Fields (a -> b)) i rc) => rc -> Compose * * Eval i (a -> b) Source #

buildNonStrict :: GivesThese (Fields (a -> b)) Identity rc => rc -> a -> b Source #

(DisjointFields a b, Lemma_AppendGivesThese (Fields a), Build a, Build b) => Build (a, b) Source # 

Associated Types

type Fields (a, b) :: [(Symbol, *)] Source #

type Shape (a, b) o :: Constraint Source #

Methods

build :: (Applicative i, GivesThese (Fields (a, b)) i rc) => rc -> Compose * * Eval i (a, b) Source #

buildNonStrict :: GivesThese (Fields (a, b)) Identity rc => rc -> (a, b) Source #

Build ((:@) s a) Source # 

Associated Types

type Fields ((:@) s a) :: [(Symbol, *)] Source #

type Shape ((:@) s a) o :: Constraint Source #

Methods

build :: (Applicative i, GivesThese (Fields (s :@ a)) i rc) => rc -> Compose * * Eval i (s :@ a) Source #

buildNonStrict :: GivesThese (Fields (s :@ a)) Identity rc => rc -> s :@ a Source #

TypeError Constraint NoBuildPair => Build (Pair l r) Source #

This is a non-instance.

Associated Types

type Fields (Pair l r) :: [(Symbol, *)] Source #

type Shape (Pair l r) o :: Constraint Source #

Methods

build :: (Applicative i, GivesThese (Fields (Pair l r)) i rc) => rc -> Compose * * Eval i (Pair l r) Source #

buildNonStrict :: GivesThese (Fields (Pair l r)) Identity rc => rc -> Pair l r Source #

Build ((a, b), c) => Build (a, b, c) Source # 

Associated Types

type Fields (a, b, c) :: [(Symbol, *)] Source #

type Shape (a, b, c) o :: Constraint Source #

Methods

build :: (Applicative i, GivesThese (Fields (a, b, c)) i rc) => rc -> Compose * * Eval i (a, b, c) Source #

buildNonStrict :: GivesThese (Fields (a, b, c)) Identity rc => rc -> (a, b, c) Source #

Build ((a, b), (c, d)) => Build (a, b, c, d) Source # 

Associated Types

type Fields (a, b, c, d) :: [(Symbol, *)] Source #

type Shape (a, b, c, d) o :: Constraint Source #

Methods

build :: (Applicative i, GivesThese (Fields (a, b, c, d)) i rc) => rc -> Compose * * Eval i (a, b, c, d) Source #

buildNonStrict :: GivesThese (Fields (a, b, c, d)) Identity rc => rc -> (a, b, c, d) Source #

Build ((a, b, c), (d, e)) => Build (a, b, c, d, e) Source # 

Associated Types

type Fields (a, b, c, d, e) :: [(Symbol, *)] Source #

type Shape (a, b, c, d, e) o :: Constraint Source #

Methods

build :: (Applicative i, GivesThese (Fields (a, b, c, d, e)) i rc) => rc -> Compose * * Eval i (a, b, c, d, e) Source #

buildNonStrict :: GivesThese (Fields (a, b, c, d, e)) Identity rc => rc -> (a, b, c, d, e) Source #

Build ((a, b, c), (d, e, f)) => Build (a, b, c, d, e, f) Source # 

Associated Types

type Fields (a, b, c, d, e, f) :: [(Symbol, *)] Source #

type Shape (a, b, c, d, e, f) o :: Constraint Source #

Methods

build :: (Applicative i, GivesThese (Fields (a, b, c, d, e, f)) i rc) => rc -> Compose * * Eval i (a, b, c, d, e, f) Source #

buildNonStrict :: GivesThese (Fields (a, b, c, d, e, f)) Identity rc => rc -> (a, b, c, d, e, f) Source #

Build ((a, b, c, d), (e, f, g)) => Build (a, b, c, d, e, f, g) Source # 

Associated Types

type Fields (a, b, c, d, e, f, g) :: [(Symbol, *)] Source #

type Shape (a, b, c, d, e, f, g) o :: Constraint Source #

Methods

build :: (Applicative i, GivesThese (Fields (a, b, c, d, e, f, g)) i rc) => rc -> Compose * * Eval i (a, b, c, d, e, f, g) Source #

buildNonStrict :: GivesThese (Fields (a, b, c, d, e, f, g)) Identity rc => rc -> (a, b, c, d, e, f, g) Source #

Build ((a, b, c, d), (e, f, g, h)) => Build (a, b, c, d, e, f, g, h) Source # 

Associated Types

type Fields (a, b, c, d, e, f, g, h) :: [(Symbol, *)] Source #

type Shape (a, b, c, d, e, f, g, h) o :: Constraint Source #

Methods

build :: (Applicative i, GivesThese (Fields (a, b, c, d, e, f, g, h)) i rc) => rc -> Compose * * Eval i (a, b, c, d, e, f, g, h) Source #

buildNonStrict :: GivesThese (Fields (a, b, c, d, e, f, g, h)) Identity rc => rc -> (a, b, c, d, e, f, g, h) Source #

rna :: QuasiQuoter Source #

rna is like rpat, but it also works for expressions. All of the sugar is supported in the dual way.

rnaA :: QuasiQuoter Source #

rnaA is like rna, but it only works for expressions and it only works inside an Applicative.

Pure Combinators

(<@) :: l -> r -> Pair l r infixr 3 Source #

Combine two types that might have Has instances for the same Symbol s. Has on the result will prefer the first argument.

NOTE WELL: Pairs are not record types. They only have Has instances.

rfrom :: forall h rc t. (Hoid h rc, rc `IsSymmetricRecordOf` t, Build t) => rc -> t Source #

rfrom @h = rsym . hoid @h

rsym :: (l `IsSymmetricRecordOf` r, Build r) => l -> r Source #

An isomorphism based on rup, when the two record types have a symmetric subtyping relation.

Isomorphism
  forall t s.
    ( s 'IsSubtypeOf' t,Build s
    , t 'IsSubtypeOf' s,Build t
    ) => rsym . id @t . rsym = id @s

rup :: forall t rc. (Build t, rc `IsSubtypeOf` t) => rc -> t Source #

rup is an upcast with respect to the width subtyping relationship of records; it builds a t from any type that has all of t's Fields.

Applicative Combinators

rtoA :: forall h t rc i. (Hoid h t, Applicative i, SymmetricRecordsA t i rc, Build t) => rc -> i t Source #

rupA :: forall t rc i. (Applicative i, Build t, GivesThese (Fields t) i (GiveAllItHasA rc)) => rc -> i t Source #

rup is an upcast with respect to the width subtyping relationship of records; it builds a t from any type that has all of t's Fields.

Conveniences

Avoid unused selectors

class NoWarnUnusedTopBind t where Source #

Merely a receptacle in which the user can syntactially use a record selector to avoid the -Wunused-top-bind warning without having to export the record selector.

  {-# OPTIONS_GHC -Werror -Wall #-}

  module Foo (Bar(MkBar)) where

  data Bar = MkBar {x,y :: Int}

  instance NoWarnUnusedTopBind Bar where noWarnUnusedTopBind MkBar{x=_,y=_} = ()
  instance Has "x" Bar
  instance Has "y" Bar
  instance Build Bar where
    {-# INLINE rupEval #-}
    rupEval = genericRupEval

x and y in that example are neither exported nor really used, but there will be no warnings.

An explicit instance of NFData, for example, will often use a similar record pattern that serves to use the selectors. On the other hand, most such instances are now quite conveient to implicitly derive, so this NoWarnUnusedTopBind class may be the most obvious way to inconsequentially "use" a record selector so as to avoid the -Wunused-top-bind warning.

Minimal complete definition

noWarnUnusedTopBind

Methods

noWarnUnusedTopBind :: Hoid t a => a -> () Source #

Splice

makeRecords :: [Name] -> Q [Dec] Source #

Declare the straight-forward Has and Build instances for a record type. A data type is a record type if it has exactly one constructor and that constructor is declared using record syntax.

An instance of a data family can be a record type; refer to that type by the name of the instance's constructor.

The generated code relies on the GHC.Generics defaults in the same way a user would; it merely relieves you from enumerating the per-field instances.

Also, the splice will declare the instances in the style of Data.Ruin.ClosedHas.