Safe Haskell | None |
---|---|

Language | Haskell2010 |

- TH splice
The

`makeRecords`

splice reifies any data type declared with record syntax into instances of this library's classes.data XY y = MkXY {x :: Int, y :: y} deriving (Generic,Show) data YX x = MkYX {y :: Bool, x :: x} deriving (Generic,Show) $(

`makeRecords`

[''XY,''YX]) -- or $(`makeRecords`

['MkXY,'MkYX]) would also workEither

`$(`

or`makeRecords`

[''XY])`$(`

splices in instances that reify the record syntax declaration of`makeRecords`

['MkXY])`MkXY`

into instances of the`ruin`

package's classes. Naming the constructor lets you reify a data family instance. The generated declarations defer to the GHC.Generics defaults as much as possible.The field names are used exactly, so use

`-XDuplicateRecordFields`

so that the automatic conversions work.

- Singleton records
The

`ruin`

library also supports anonymous record types.The

`:@`

newtype is the singleton record type.*> :t

`dub`

`Label`

s -> a -> s`:@`

a *> :t`dub`

#x -- This uses -XOverloadedLabels. a -> "x"`:@`

a *> :t`undub`

#z "z"`:@`

a -> aAnd a tuple of record types is also a record type if the component record types do not have any fields with the same name. Currently it supports up to 8 tuple components. Note that you can nest them if you need more!

- Projection
The

`Has`

class provides the`extricate`

projection, which allows careful control of strictness.*> :t

`runEval`

.`extricate`

#x`Has`

"x" t => t ->`FieldType`

"x" t`extricate`

can navigate nested records with intuitive syntax.*> :t

`runEval`

.`extricate`

(#x . #y) (`Has`

"y" (`FieldType`

"x" t),`Has`

"x" t) => t ->`FieldType`

"y" (`FieldType`

"x" t)

- Conversion
The

`Build`

and`IsSubtypeOf`

constraints provide the`rup`

upcast with respect to record types'*width subtyping relationship*.`IsSubtypeOf`

and`rup`

essentially delegate to`Has`

and`extricate`

for each necessary field.*> let (y,z) =

`rup`

(`dub`

#z (), MkXY {x=undefined,y="ash"}) *> (`undub`

#y y,`undub`

#z z) ("ash",())The

`rsym`

isomorphism is`rup`

with a specialized type requiring that the two types be subtypes of one another.*> let (y,z,x) =

`rsym`

(`dub`

#z (), MkXY {x=1,y="ash"}) *> (`undub`

#x x,`undub`

#y y,`undub`

#z z) (1,"ash",())

- Ascription
The

`hoid`

function is a family of identity functions, indexed by types of any order. It let's you ascribe types without having to fully apply them, which is often useful for polymorphic record types.*> :t

`hoid`

@XY XY t -> XY t *> :t`hoid`

@(->) (t -> t1) -> t -> t1Record types have a notion of

*shape*; see`Shape`

for details. The`UnifyShape`

constraint and the`asShapeOf`

ascription can both be used to drive type inference. There are some combinators whose types are very unweildy until the involved record types' shapes are fixed.The "complement" of a record type's shape is roughly the types of the record type's fields. The

`UnifyFieldTypes`

constraint and the`asFieldTypesOf`

combinator support ascribing just that.*> :t \x y rc -> (

`dub`

#x x,`dub`

#y y) ``asFieldTypesOf`

` rc`FieldType`

"x" rc ->`FieldType`

"y" rc -> proxy rc -> ("x"`:@`

`FieldType`

"x" rc, "y"`:@`

`FieldType`

"y" rc)Note that the second argument must have at least the fields of the first argument, but may have a different shape, which in particular means it may have "extra" fields.

You'll generally use the

`hoidProxy`

and`proxyOf`

combinators to create the second argument of`asFieldTypesOf`

.*> :t

`hoidProxy`

@XY Data.Proxy.Proxy (XY t) *> :t`proxyOf`

a -> Data.Proxy.Proxy a

- Directed conversion
The

`rfrom`

and`rto`

combinators are`rsym`

but additionally require an explicit type argument (like`hoid`

) so that they read well.*> :t (\(x,y) -> (

`undub`

#x x,`undub`

#y y)) .`rfrom`

@XY XY t -> (Int,t) *>`rto`

@XY (`dub`

#x 1,`dub`

#y False) XY {x = 1, y = False}

- Quasiquoter
The

`rna`

quasiquoter enables named arguments for functions.*> :t \[

`rna`

|x y|] -> x * x + 3 x * y - 2 * y * y Num a => ("x"`:@`

a,"y"`:@`

a) -> aIt can also create anonymous records.

*> :t \x y -> [

`rna`

|x y|] a -> a1 -> ("x"`:@`

a, "y"`:@`

a1)There are some usefuls syntactic sugars; see

`rna`

for details.*> :t [

`rna`

| id@x show@y |] Show a1 => ("x"`:@`

(a -> a), "y"`:@`

(a1 -> String)) *> :t \_x' _y' -> [`rna`

| XY (_...') x y |] Int -> y -> XY y

- Suppressing fields
The lopsided combinator

`<@`

allows for left-biased field overlap.*> let xy = (

`dub`

#x 1,`dub`

#y False) *> let yz = (`dub`

#y 4,`dub`

#z undefined) *> let f [`rna`

|x y|] = x + y *> f $`rsym`

$ yz`<@`

xy 5The

`hide`

combinator hides some fields, without having to replace to them.*> :t

`extricate`

#x $`hide`

#x $`dub`

#x True <interactive>:1:1: error: * ruin: The field `x' is hidden in the type "x"`:@`

Bool * ... *>`runEval`

$`extricate`

#x $`hide`

#y $`dub`

#x True TrueYou can hide multiple fields at once:

*> :t

`hide`

(#x . #y) rc ->`Hide`

'["x", "y"] rc TrueNote that that hides the

`x`

field and the`y`

field --- it doesn't hide a nested field`x.y`

.

- Partitioning records
Sometimes suppressing a field isn't enough, and you need to actually remove it. In that case, use the partitioning combinators.

The

`rdrop`

combinator is a stronger version of`hide`

; given a list of labels and a record, it creates an anonymous record with the fields of the given record other than the given labels.*>

`rdrop`

(#x . #y) (`dub`

#x 'x',`dub`

#y 'y',`dub`

#z 'z')`MkTup1`

(`dub`

#z 'z')Instead of listing those labels explicitly, you can use

`fieldLabelsOf`

to take them from another known record type.Note that the

`rsym`

combinator can split a record type into two other record types that fully partition the full origial.data AB a b = {a::a,b::b} deriving (Generic,Show) data CD c d = {c::c,d::d} deriving (Generic,Show) $(makeRecords [''AB,''CD]) *>

`hoid`

@AB ***`hoid`

@CD $`rsym`

[`rna`

|mempty@a mempty@b mempty@c mempty@d|] (Monoid a3, Monoid a2, Monoid a1, Monoid a) => t -> (AB a2 a3, CD a a1)The

`rtake`

combinator is similar, except it completely infers the type of the second component; specifically, the second component is an anonymous record type whose fields are those that are "leftover" from creating the first component. Otherwise, it's just like`rsym`

.

- Custom errors
Most of the error messages are easy to read.

*> (\[

`rna`

|x z|] -> x + z) $`rsym`

(`dub`

#x 1,`dub`

#y 2) <interactive>:3:1: error: * ruin: Could not find a field `z' in the type "x"`:@`

t or in the type "y"`:@`

a * ...

- Fieldwise combinators
Record types support an interface very similar to Applicative functors, based on fieldwise operations.

The

`rpure`

,`rmonopure`

,`rmap`

, and`rsplat`

combinators are designed to mimic the familiar`pure`

,`<$>`

, and`<*>`

combinators.*> let isZero x = 0 == x *> [

`rna`

|show succ pred isZero|] ``rsplat`

``rmonopure`

(4 :: Int) (`dub`

#show "4",`dub`

#succ 5,`dub`

#pred 3,`dub`

#isZero False)Others:

`rmempty`

,`rmappend`

, and`rlabel`

. See this section for more information.

- Applicative variants
Many combinators have variants that work in an Applicative functor. In particular, the

`rnaA`

quasiquoter only works for expressions, and it builds records in an Applicative functor, with the effects of each field ordered as in the quasiquoter text.*> let x = [1,2] *> let y = ["y1","y2"] *> mapM_ print [

`rnaA`

|XY x y|] MkXY {x = 1,y = "y1"} MkXY {x = 1,y = "y2"} MkXY {x = 2,y = "y1"} MkXY {x = 2,y = "y2"} *> mapM_ print [`rnaA`

|XY y x|] MkXY {x = 1,y = "y1"} MkXY {x = 2,y = "y1"} MkXY {x = 1,y = "y2"} MkXY {x = 2,y = "y2"}

- data s :@ a
- dub :: Label s -> a -> s :@ a
- undub :: Label s -> (s :@ a) -> a
- class Has s t where
- extricate :: forall ss t. DeepHas ss t => Labels ss -> t -> Eval (DeepFieldType ss t)
- rna :: QuasiQuoter
- rnaA :: QuasiQuoter
- data Hide ss rc
- hide :: Labels ss -> rc -> Hide ss rc
- class Build t where
- (<@) :: l -> r -> Pair l r
- rdrop :: (rc ~ Rcrd (DifferenceByFst (Fields t) fs), Build rc, t `IsSubtypeOf` rc) => Labels fs -> t -> rc
- rfrom :: forall h rc t. (Hoid h rc, rc `IsSymmetricRecordOf` t, Build t) => rc -> t
- rsym :: (l `IsSymmetricRecordOf` r, Build r) => l -> r
- rtake :: (leftovers ~ Rcrd (DifferenceByFst (Fields t) (FieldNames taken)), Build (taken, leftovers), t `IsSymmetricRecordOf` (taken, leftovers)) => t -> (taken, leftovers)
- rto :: forall h t rc. (Hoid h t, rc `IsSymmetricRecordOf` t, Build t) => rc -> t
- rup :: forall t rc. (Build t, rc `IsSubtypeOf` t) => rc -> t
- rfromA :: forall h rc t i. (Hoid h rc, Applicative i, SymmetricRecordsA t i rc, Build t) => rc -> i t
- rsymA :: (Applicative i, SymmetricRecordsA t i rc, Build t) => rc -> i t
- rtoA :: forall h t rc i. (Hoid h t, Applicative i, SymmetricRecordsA t i rc, Build t) => rc -> i t
- rupA :: forall t rc i. (Applicative i, Build t, GivesThese (Fields t) i (GiveAllItHasA rc)) => rc -> i t
- class FPure a s b where
- rlabel :: (Build t, GivesThese (Fields t) Identity (RPure RLabel)) => t
- rmempty :: (Build t, GivesThese (Fields t) Identity (RPure RMEmpty)) => t
- rmap :: forall fun rc rfun t. (Build rfun, Build t, GivesThese (Fields rfun) Identity (RPure fun), GivesThese (Fields t) Identity (RSplat rfun rc), UnifyShape rfun t, UnifyShape rc t) => fun -> rc -> t
- rmapA :: forall fun i rc rfun t. (Applicative i, Build rfun, Build t, GivesThese (Fields rfun) Identity (RPure fun), GivesThese (Fields t) i (RSplatA rfun rc), UnifyShape rfun t, UnifyShape rc t) => fun -> rc -> i t
- rmappend :: (Build t, GivesThese (Fields t) Identity (RMAppend t t)) => t -> t -> t
- rmonopure :: (Build t, GivesThese (Fields t) Identity (RPure (RMonoPure a))) => a -> t
- rpolypure :: (Build t, GivesThese (Fields t) Identity (RPure a)) => a -> t
- rpure :: (Build t, GivesThese (Fields t) Identity (RPure a)) => a -> t
- rsappend :: (Build t, GivesThese (Fields t) Identity (RSAppend t t)) => t -> t -> t
- rsplat :: (Build t, GivesThese (Fields t) Identity (RSplat rfun rc), UnifyShape rc t, UnifyShape rfun t) => rfun -> rc -> t
- rsplatA :: (Applicative i, Build t, GivesThese (Fields t) i (RSplatA rfun rc), UnifyShape rc t, UnifyShape rfun t) => rfun -> rc -> i t
- type family UnifyFieldTypes (ss :: [Symbol]) (t :: *) (h :: *) :: Constraint where ...
- type UnifyShape l r = (Shape l r, Shape r l)
- asFieldTypesOf :: UnifyFieldTypes (FieldNames t) t rc => t -> proxy rc -> t
- asShapeOf :: UnifyShape l r => l -> r -> l
- hoid :: forall t a. Hoid t a => a -> a
- hoidProxy :: forall t a. Hoid t a => Proxy a
- data Label s
- type Labels fs = Labels_ '[] -> Labels_ fs
- class NoWarnUnusedTopBind t where
- fieldLabelsOf :: forall t proxy. proxy t -> Labels (FieldNames t)
- makeRecords :: [Name] -> Q [Dec]
- mkLabel :: forall s. Label s
- mkLabels :: forall fs. Labels fs
- proxyOf :: a -> Proxy a

# Singleton records

A record type with a single field.

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

Functor ((:@) s) Source # | |

Generic1 ((:@) s) Source # | |

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

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

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

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

Generic ((:@) s a) Source # | |

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

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

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

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

Build ((:@) s a) Source # | |

type FieldType s1 ((:@) s2 a) Source # | |

type Rep1 ((:@) s) Source # | |

type Rep ((:@) s a) Source # | |

type Fields ((:@) s a) Source # | |

type Shape ((:@) s _) o Source # | |

# Accessing parts of records

`t`

has a field named `s`

that inhabits

.`FieldType`

s t

`extricate1`

projects out the field, with special care to
strictness. The `Eval`

layer provides a stopping point for the
projection computation. Without this layer, one would have to force
the value itself in order to force the extrication enough so that
the rest of `t`

could be GC'd. On the contrary, `case `

neither retains `extricate1`

t
of `Done`

x -> x`t`

nor forces `x`

.

*Strictness*- Forcing the
`Done`

layer of`extricate1`

forces enough of`t`

to reach the field but doesn't force the field. This is difficult to formalize in a general and illuminating way, so this law is instantiated below for a simple record type.data XY = MkXY {x,y :: Int}

`extricate1`

#x (undefined :: XY) = undefined flip seq () $`extricate1`

#x (MkXY undefined undefined) = ()

type FieldType s t :: * Source #

Default: `GenericFieldType`

extricate1 :: Label s -> t -> Eval (FieldType s t) Source #

Default: `genericExtricate1`

extricate1 :: (Generic t, GBox (IsABox (Rep t)) t, GenericHas (Rep t) s (FieldType s t)) => Label s -> t -> Eval (FieldType s t) Source #

Default: `genericExtricate1`

TypeError Constraint (NoSuchField s ()) => Has s () Source # | This is a non-instance. |

Has s a => Has s (Tup1 a) Source # | |

ClosedHas s (R fd) => Has s (R fd) Source # | |

(DisjointFields a b, Has s (Pair a b)) => Has s (a, b) Source # | |

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

TypeError Constraint (NoFun (Symbol -> * -> Constraint) Has) => Has s (a -> b) Source # | This is a non-instance. |

MightHave (Pair l r) (Find (Pair l r) s) (Pair l r) s (FieldType s (Pair l r)) => Has s (Pair l r) Source # | |

Has_Hide (Elem Symbol s sHiddens) s rc => Has s (Hide sHiddens rc) Source # | |

Has s ((a, b), c) => Has s (a, b, c) Source # | |

Has s ((a, b), (c, d)) => Has s (a, b, c, d) Source # | |

Has s ((a, b, c), (d, e)) => Has s (a, b, c, d, e) Source # | |

Has s ((a, b, c), (d, e, f)) => Has s (a, b, c, d, e, f) Source # | |

Has s ((a, b, c, d), (e, f, g)) => Has s (a, b, c, d, e, f, g) Source # | |

Has s ((a, b, c, d), (e, f, g, h)) => Has s (a, b, c, d, e, f, g, h) Source # | |

extricate :: forall ss t. DeepHas ss t => Labels ss -> t -> Eval (DeepFieldType ss t) Source #

`extricate`

project a field out of nested records by iterating
`extricate1`

.

The first argument is a function type so that the syntax can use
`.`

to specify a sequence of labels.

`extricate`

id = return`extricate`

(#s . ss) =`extricate1`

#s Control.Monad.`>=>`

`extricate`

ss

rna :: QuasiQuoter Source #

Named arguments for functions.

(\[`rna`

|x] -> x) ::`Tup1`

("x"`:@`

a) -> a (\[`rna`

|x y] -> (x,y)) :: ("x"`:@`

a,"y"`:@`

b) -> (a,b) (\[`rna`

|y x] -> (x,y)) :: ("y"`:@`

b,"x"`:@`

a) -> (a,b)

And so on. The `Has`

and `Build`

classes support such tuples up to
8 components.

There are four pieces of special syntax, none of which can be escaped.

A

`@`

allows a different variable name than the field name.(\f [

`rna`

|l@x|] [`rna`

|r@x|] -> f l r) :: (a -> b -> c) ->`Tup1`

("x"`:@`

a) ->`Tup1`

("x"`:@`

b) -> c- A name of
`_`

is a wildcard pattern. A leading word of the form

`(<prefix>...<suffix>)`

adds a prefix and/or suffix to all of the variable names. This affects even the names given with`@`

syntax. It does not affect wildcards.(\[

`rna`

|(...L) x y|] [`rna`

|(r_...') x y|] -> xL == r_x' && yL == r_y') :: (Eq a,Eq b) => ("x"`:@`

a,"y"`:@`

b) -> ("x"`:@`

a,"y"`:@`

b) -> BoolA

`!`

at the beginning of the pattern makes it strict.-- strict (\[

`rna`

|!x|] -> Just x) ::`Tup1`

("x"`:@`

a) -> Maybe a -- strict (\[`rna`

|!x@foo|] -> Just x) ::`Tup1`

("foo"`:@`

a) -> Maybe a -- strict (\[`rna`

|!x@!|] -> Just x) ::`Tup1`

("!"`:@`

a) -> Maybe a -- not strict (\[`rna`

|x@!|] -> Just x) ::`Tup1`

("!"`:@`

a) -> Maybe aNote a

`~`

pattern for binding would be redundant, since the bindings are ultimately variable bindings. Though it may be useful to apply a tilde pattern to the entire quasiquote.- A leading word that is capitalized is interpreted as the name of
a record type and is ascribed via
`rfrom`

.

```
data XY x y = MkXY {x :: x,y :: y}
(\[
````rna`

| XY x y|] -> (x,y)) :: XY t t1 -> (t, t1)

When both are present, the type name must precede the prefix and/or suffix.

`rna`

also works as an expression. All of the sugar except
wildcards is supported in the dual way.

rnaA :: QuasiQuoter Source #

- it only works for expressions,
- it only works inside an
`Applicative`

.

# Hiding fields

Deny the

instance for each of `Has`

`ss`

.

# Record types' *width subtyping*

## Lowest-level combinators

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

).

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

Each element of this list is the name of a field and its
type in `t`

. Default: `GenericFields`

.

type Shape (t :: *) (o :: *) :: Constraint Source #

The shape of a record type is its most general type, the one
that all instances of that record type are specializations of.
Unless you're being clever, the shape of the type class index `t`

is `t`

, since that `t`

is usually as polymorphic as it could be
(i.e. the value that the type variables within `t`

take on do not
change how it instantiates `Build`

).

The

constraint requires --- via `Shape`

t o`~`

--- that `o`

has the same shape as `t`

. It must use `~`

to assert this
requirement, so that it can guide type inference.

`Shape`

defaults to `GenericShape`

, which is correct for data
types declared with record syntax except for data family
instances. See `GenericShape`

for more info.

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

The laws for `build`

are given without loss of generality in
terms of `rupEval`

.

*Eta*- An
eta rule.
t

`<$`

`rupEval`

t =`rupEval`

tThis law reasonably requires that

`t`

`Has`

all of its own`Fields`

. *Strictness*- The
`rupEval`

function is strict in its argument, but it's only strict enough to retrieve the thunks for each of the necessary fields, without forcing those thunks.seq (

`rupEval`

rc) = seq (`extricate1`

#f1 rc) . seq (`extricate1`

#f2 rc) ... . seq (`extricate1`

#fN rc)

If `rc`

is a typical single-constructor record type declared with
record syntax and has fields for all of `t`

's `Fields`

, then the
*Strictness* law simplifies to `seq (`

.`rupEval`

rc) = seq rc

**Note**- A
`GHC.Generics`

default is available as`genericBuild`

. We do not provide a`DefaultSignature`

because it is most often critical for performance that`build`

is inlined, which requires an explicit`INLINE`

pragma (the RHS size gets too large for inferred inlining with even just three fields). We thus recommend the following.instance

`Build`

Foo where {-# INLINE`build`

#-}`build`

=`genericBuild`

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

Like `build`

, but maximally non-strict instead of having the
*Strictness* law. Defaults to `genericBuildNonStrict`

, but beware
that a manual `INLINE`

pragma is likely as useful as it is for
`build`

.

seq (`build`

rc) (`buildNonStrict`

rc) =`runEval`

(`build`

rc)

buildNonStrict :: (Fields t ~ GenericFields t, Generic t, GenericBuild t (Rep t), GivesThese (Fields t) Identity rc) => rc -> t Source #

Like `build`

, but maximally non-strict instead of having the
*Strictness* law. Defaults to `genericBuildNonStrict`

, but beware
that a manual `INLINE`

pragma is likely as useful as it is for
`build`

.

seq (`build`

rc) (`buildNonStrict`

rc) =`runEval`

(`build`

rc)

Build () Source # | |

Build a => Build (Tup1 a) Source # | |

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

TypeError Constraint (NoFun (* -> Constraint) Build) => Build (a -> b) Source # | This is a non-instance. |

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

Build ((:@) s a) Source # | |

TypeError Constraint NoBuildPair => Build (Pair l r) Source # | This is a non-instance. |

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

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

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

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

Build ((a, b, c, d), (e, f, g)) => Build (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 # | |

## Pure combinators

rdrop :: (rc ~ Rcrd (DifferenceByFst (Fields t) fs), Build rc, t `IsSubtypeOf` rc) => Labels fs -> t -> rc Source #

Create an anonymous record that contains the fields of `t`

that
are not named in `fs`

.

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

rtake :: (leftovers ~ Rcrd (DifferenceByFst (Fields t) (FieldNames taken)), Build (taken, leftovers), t `IsSymmetricRecordOf` (taken, leftovers)) => t -> (taken, leftovers) Source #

Split a record into two separate types, where the second type is an anonymous record defined as the leftovers from the first type.

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

## Applicative combinators

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

rsymA :: (Applicative i, SymmetricRecordsA t i rc, Build t) => rc -> i t Source #

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 #

# Fieldwise combinators

The types of these combinators are not useful in the
abstract. However, once the `Shape`

of any argument record type
or result record type is fixed, the types reduce to something
plain.

*> :t`rsplat`

[`rna`

|show@x id@y|] Show t => ("x"`:@`

t, "y"`:@`

t1) -> ("x"`:@`

String, "y"`:@`

t1)

A basic, self-contained example:

data PrintAndTime = MkPrintAndTime instance (Show a,f ~ (a -> IO (a,Integer))) =>`FPure`

PrintAndTime s f where`fpure`

_ x = do print x (,) x <$> System.CPUTime.getCPUTime *>`rmapA`

MkPrintAndTime (`dub`

#x "OK",`dub`

#y ()) "OK" () (`dub`

#x ("OK",43062500000000),`dub`

#y ((),43062500000000))

rmap :: forall fun rc rfun t. (Build rfun, Build t, GivesThese (Fields rfun) Identity (RPure fun), GivesThese (Fields t) Identity (RSplat rfun rc), UnifyShape rfun t, UnifyShape rc t) => fun -> rc -> t infixl 4 Source #

rmapA :: forall fun i rc rfun t. (Applicative i, Build rfun, Build t, GivesThese (Fields rfun) Identity (RPure fun), GivesThese (Fields t) i (RSplatA rfun rc), UnifyShape rfun t, UnifyShape rc t) => fun -> rc -> i t infixl 4 Source #

If the following constraint holds for every field `s`

in `t`

,
then `fun`

can map `rc`

to `t`

within an `Applicative`

functor `i`

.

`FPure`

fun s (`FieldType`

s rc -> i (`FieldType`

s t))

> :t \fun ->`rmapA`

fun .`hoid`

@((`:@`

) "x") \fun ->`rmapA`

fun .`hoid`

@((`:@`

) "x") :: (`FPure`

fun "x" (t -> i t1), Applicative i) => fun -> "x"`:@`

t -> i ("x"`:@`

t1)

rsplat :: (Build t, GivesThese (Fields t) Identity (RSplat rfun rc), UnifyShape rc t, UnifyShape rfun t) => rfun -> rc -> t infixl 4 Source #

rsplatA :: (Applicative i, Build t, GivesThese (Fields t) i (RSplatA rfun rc), UnifyShape rc t, UnifyShape rfun t) => rfun -> rc -> i t infixl 4 Source #

# Ascription

type family UnifyFieldTypes (ss :: [Symbol]) (t :: *) (h :: *) :: Constraint where ... Source #

UnifyFieldTypes '[] _ _ = () | |

UnifyFieldTypes (s ': ss) t h = (FieldType s t ~ FieldType s h, UnifyFieldTypes ss t h) |

type UnifyShape l r = (Shape l r, Shape r l) Source #

Unify the shape of two record types; see `Shape`

.

asFieldTypesOf :: UnifyFieldTypes (FieldNames t) t rc => t -> proxy rc -> t Source #

asShapeOf :: UnifyShape l r => l -> r -> l Source #

Like `asTypeOf`

, but doesn't require that the fields have the
same types, only that the record types have the same shape.

hoid :: forall t a. Hoid t a => a -> a Source #

A family of identity functions indexed by possibly higher-order
types.

asserts that `hoid`

@t`a`

is either equal to `t`

or is
an application of `t`

.

The `Hoid`

type family vanishes if the kind of `t`

is defined
enough to fully determine the arity of `t`

. If `Hoid`

doesn't
vanish in a use case, then `hoid`

is not intended for use in that
case.

# Conveniences

Use `-XOverloadedLabels`

to create labels. For example, ```
#x ::
Label "x"
```

.

Or use `mkLabel`

.

type Labels fs = Labels_ '[] -> Labels_ fs Source #

This type is an instance of a type-level difference list, so that
sequences of labels can be written as `#x . #y . #z :: `

, for example.`Labels`

'["x","y","z"]

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.

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

fieldLabelsOf :: forall t proxy. proxy t -> Labels (FieldNames t) Source #

Get the labels of a record type's fields.

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.