HList-0.4.1.0: Heterogeneous lists

Data.HList.Variant

Description

The HList library

See CommonMain#Variant for the public (safe) interface.

The implementation here follows Data.Dynamic, though Typeable is not needed.

See `broken/VariantP.hs` and `broken/VariantOld.hs` for different approaches to open sums.

Synopsis

# Labels for doctests

````>>> ````import Data.HList.RecordPuns
````>>> ````let x = Label :: Label "x"
````>>> ````let y = Label :: Label "y"
````>>> ````let z = Label :: Label "z"
````>>> ````let _left = Label :: Label "left"
````>>> ````let _right = Label :: Label "right"
``````
````>>> ````:set -XQuasiQuotes -XViewPatterns -XDataKinds
``````
• - * Creating Variants

It is necessary to specify the order in which the fields occur, using a data type like

````>>> ````let p = Proxy :: Proxy '[Tagged "left" Char, Tagged "right" Int]
``````

Then this argument can be passed into `mkVariant`

````>>> ````let v = mkVariant _left 'x' p
````>>> ````let w = mkVariant _right 5  p
``````
````>>> ````:t v
```v :: Variant '[Tagged "left" Char, Tagged "right" Int]
```
````>>> ````:t w
```w :: Variant '[Tagged "left" Char, Tagged "right" Int]
```
````>>> ````[v,w]
```[V{left='x'},V{right=5}]
```

## Alternative: a `Record` as the Proxy

The type of mkVariant also allows using a `Record` as the proxy. For example:

````>>> ````:{
```let p2 = [pun| left right |] where
left = 'a'
right = (4::Int)
:}
```
````>>> ````let v2 = mkVariant _left 'x' p2
````>>> ````let w2 = mkVariant _right 5  p2
``````
````>>> ````:t v2
```v2 :: Variant '[Tagged "left" Char, Tagged "right" Int]
```
````>>> ````:t w2
```w2 :: Variant '[Tagged "left" Char, Tagged "right" Int]
```
````>>> ````(v2,w2)
```(V{left='x'},V{right=5})
```

## A polymorphic Proxy

It is also possible to leave the `Char` and `Int` as type variables, and have them inferred.

````>>> ````let p3 = Proxy :: Proxy '[Tagged "left" a, Tagged "right" b]
``````

Using `p3` takes some care. The following attempt shows the problem:

````>>> ````:{
```let v3' = mkVariant _left 'x' p3
w3' = mkVariant _right (5::Int) p3
:}
```
````>>> ````:t v3'
```v3' :: Variant '[Tagged "left" Char, Tagged "right" b]
```
````>>> ````:t w3'
```w3' :: Variant '[Tagged "left" a, Tagged "right" Int]
```

Here each use of `p3` does not constrain the type of the other use. In some cases those type variables will be inferred from other constraints, such as when putting the variants into a list

````>>> ````[v3', w3']
```[V{left='x'},V{right=5}]
```

In other cases the other tags will be defaulted to (), at least if `ExtendedDefaultRules` is enabled:

````>>> ````v3'
```V{left='x'}
```
````>>> ````:set -XNoExtendedDefaultRules
````>>> ````v3'
```...
...No instance for (Show ...) arising from a use of ‘print’
...
```

Another way around this issue is to make sure that the proxy is bound in a monomorphic pattern. These are patterns that allow name shadowing.

An example of the case:

````>>> ````:{
```let (v3,w3) = case p3 of
p -> (mkVariant _left 'x' p,
mkVariant _right (5 :: Int) p)
:}
```
````>>> ````:t v3
```v3 :: Variant '[Tagged "left" Char, Tagged "right" Int]
```
````>>> ````:t w3
```w3 :: Variant '[Tagged "left" Char, Tagged "right" Int]
```

data Variant vs Source

`Variant vs` has an implementation similar to `Dynamic`, except the contained value is one of the elements of the `vs` list, rather than being one particular instance of `Typeable`.

````>>> ````v .!. _right
```Nothing
```
````>>> ````v .!. _left
```Just 'x'
```

In some cases the `pun` quasiquote works with variants,

````>>> ````let f [pun| left right |] = (left,right)
````>>> ````f v
```(Just 'x',Nothing)
```
````>>> ````f w
```(Nothing,Just 5)
```
````>>> ````let add1 v = hMapV (Fun succ :: Fun '[Enum] '()) v
``````
````>>> ````f (add1 v)
```(Just 'y',Nothing)
```
````>>> ````f (add1 w)
```(Nothing,Just 6)
```

Constructors

 Variant !Int Any

Instances

 Relabeled Variant TypeIndexed Variant TIC (ExtendsVariant b t, ProjectVariant s a, ProjectExtendVariant s t, HLeftUnion b s bs, HRLabelSet bs, HRearrange (LabelsOf t) bs t) => Projected Variant s t a b `Prism (Variant s) (Variant t) (Variant a) (Variant b)` HUpdateVariantAtLabelCxt k l e v v' n _e => HUpdateAtLabel k Variant l e v v' ```hUpdateAtLabel x e' (mkVariant x e proxy) == mkVariant x e' proxy hUpdateAtLabel y e' (mkVariant x e proxy) == mkVariant x e proxy``` (HPrism k x s t a b, (~) (* -> * -> *) to (->)) => Labelable k x Variant s t a b make a `Prism (Variant s) (Variant t) a b` (HasField k x (Record vs) a, HFindLabel k x vs n, HNat2Integral n) => HasField k x (Variant vs) (Maybe a) (ApplyAB f te te', HMapCxt Variant f ((:) * l ls) ((:) * l' ls')) => HMapAux Variant f ((:) * te ((:) * l ls)) ((:) * te' ((:) * l' ls')) ApplyAB f te te' => HMapAux Variant f ((:) * te ([] *)) ((:) * te' ([] *)) ((~) * le (Tagged k l (Maybe e)), HOccursNot * (Label k l) (LabelsOf v)) => HExtend le (Variant v) Extension for Variants prefers the first value```(l .=. Nothing) .*. v = v (l .=. Just e) .*. _ = mkVariant l e Proxy``` (Unvariant ((:) * txy ([] *)) txy, (~) * tx (Tagged k t x), (~) * ty (Tagged k t y), (~) * txy (Tagged k t (x, y))) => HUnzip Variant ((:) * tx ([] *)) ((:) * ty ([] *)) ((:) * txy ([] *)) (HUnzip Variant ((:) * x2 xs) ((:) * y2 ys) ((:) * xy2 xys), (~) * tx (Tagged k t x), (~) * ty (Tagged k t y), (~) * txy (Tagged k t (x, y))) => HUnzip Variant ((:) * tx ((:) * x2 xs)) ((:) * ty ((:) * y2 ys)) ((:) * txy ((:) * xy2 xys)) (Bounded x, Bounded z, (~) [*] (HRevAppR * ((:) * (Tagged k1 s x) xs) ([] *)) ((:) * (Tagged k t z) sx), MkVariant k t z ((:) * (Tagged k1 s x) xs)) => Bounded (Variant ((:) * (Tagged k s x) xs)) Enum x => Enum (Variant ((:) * (Tagged k s x) ([] *))) While the instances could be written Enum (Variant '[]) Eq/Ord which cannot produce values, so they have instances for empty variants (`unsafeEmptyVariant`). Enum can produce values, so it is better that `fromEnum 0 :: Variant '[]` fails with No instance for `Enum (Variant '[])` than producing an invalid variant. (Enum x, Bounded x, Enum (Variant ((:) * y z))) => Enum (Variant ((:) * (Tagged k s x) ((:) * y z))) ````>>> ````let t = minBound :: Variant '[Tagged "x" Bool, Tagged "y" Bool] ````>>> ````[t .. maxBound] ```[V{x=False},V{x=True},V{y=False},V{y=True}] ````Odd behavior`There are some arguments that this instance should not exist.The last type in the Variant does not need to be Bounded. This means that `enumFrom` behaves a bit unexpectedly:````>>> ````[False .. ] ```[False,True] ```````>>> ````[t .. ] ```[V{x=False},V{x=True},V{y=False},V{y=True},V{y=*** Exception: Prelude.Enum.Bool.toEnum: bad argument ```This is a "feature" because it allows an `Enum (Variant '[Tagged "a" Bool, Tagged "n" Integer])`Another difficult choice is that the lower bound is `fromEnum 0` rather than `minBound`:````>>> ````take 5 [ minBound :: Variant '[Tagged "b" Bool, Tagged "i" Int] .. ] ```[V{b=False},V{b=True},V{i=0},V{i=1},V{i=2}] ``` (Eq (Variant xs), Eq x) => Eq (Variant ((:) * x xs)) Eq (Variant ([] *)) (Typeable * (Variant v), GfoldlVariant v v, GunfoldVariant v v, VariantConstrs v) => Data (Variant v) (Ord x, Ord (Variant xs)) => Ord (Variant ((:) * x xs)) Ord (Variant ([] *)) ReadVariant v => Read (Variant v) A corresponding read instance ShowVariant vs => Show (Variant vs) Variants are not opaque (Monoid x, Monoid (Variant ((:) * a b))) => Monoid (Variant ((:) * (Tagged k t x) ((:) * a b))) XXX check this mappend is legal (Unvariant ((:) * (Tagged k t x) ([] *)) x, Monoid x) => Monoid (Variant ((:) * (Tagged k t x) ([] *))) (SameLength * * s a, ExtendsVariant s a, SameLength * * b t, ExtendsVariant b t) => Rearranged [*] Variant s t a b Typeable ([*] -> *) Variant type LabelableTy Variant = LabelablePrism type HExtendR le (Variant v) = Variant ((:) * (UnMaybe le) v)

## Unsafe operations

Arguments

 :: Int n -> v -> Variant vs

This is only safe if the n'th element of vs has type `Tagged t v`

Safe when (e ~ e') given that

```Tagged t e ~ HLookupByHNatR n v
Tagged t' e' ~ HLookupByHNatR n v'```

`hUpdateAtLabel` is the safe version

castVariant :: (RecordValuesR v ~ RecordValuesR v', SameLength v v') => Variant v -> Variant v' Source

in ghc>=7.8, `coerce` is probably a better choice

unsafeUnVariant :: Variant v -> e Source

private destructor. This is safe only if the value contained actually has type `e`

This function is unsafe because it can lead to a runtime error when used together with the `HExtend` instance (.*.)

````>>> ````print \$ (Label :: Label "x") .=. (Nothing :: Maybe ()) .*. unsafeEmptyVariant
```V{*** Exception: invalid variant
```

use `mkVariant1` instead

# Public constructor

class HasField x (Variant vs) (Maybe v) => MkVariant x v vs | x vs -> v where Source

Methods

Arguments

 :: Label x the tag -> v value to be stored -> proxy vs a helper to fix the ordering and types of the potential values that this variant contains. Typically this will be a `Proxy`, `Record` or another `Variant` -> Variant vs

Instances

 (HFindLabel k x vs n, HNat2Integral n, HasField k x (Variant vs) (Maybe v)) => MkVariant k x v vs

mkVariant1 :: Label k l -> e -> Variant ((:) * (Tagged k l e) ([] *)) Source

# Public destructor

`hLookupByLabel` (synonym `.!.`)

```(.!.)             :: Variant v -> Label x -> Maybe e
hLookupByLabel    :: Label x -> Variant v -> Maybe e```

`hPrism` and `hLens'` combine this with `mkVariant`

splitVariant1' :: Variant (x : xs) -> Either x (Variant xs) Source

x ~ Tagged s t

# Prism

class (SameLength s t, SameLabels s t) => HPrism x s t a b | x s -> a, x t -> b, x s b -> t, x t a -> s where Source

Make a `Prism (Variant s) (Variant t) a b` out of a Label.

See Data.HList.Labelable.`hLens'` is a more overloaded version.

Few type annotations are necessary because of the restriction that `s` and `t` have the same labels in the same order, and to get "t" the "a" in "s" is replaced with "b".

Methods

hPrism :: (Choice p, Applicative f) => Label x -> p a (f b) -> p (Variant s) (f (Variant t)) Source

Instances

 (MkVariant k x b t, HasField k x (Variant s) (Maybe a), SameLength * * s t, SameLabels [*] [*] s t, H2ProjectByLabels ((:) * (Label k x) ([] *)) s si so, H2ProjectByLabels ((:) * (Label k x) ([] *)) t ti to, (~) [*] so to, HUpdateAtLabel k Variant x b s t, HUpdateAtLabel k Variant x a t s) => HPrism k x s t a b

class ShowVariant vs where Source

helper class for defining the Show instance

Methods

Instances

 (ShowLabel k l, Show v, (~) * lv (Tagged k l v)) => ShowVariant ((:) * lv ([] *)) (ShowLabel k l, Show v, ShowVariant ((:) * w ws)) => ShowVariant ((:) * (Tagged k l v) ((:) * w ws))

# Show

Methods

Instances

 ReadVariant ([] *) (ShowLabel k l, Read v, ReadVariant vs, HOccursNot * (Label k l) (LabelsOf vs)) => ReadVariant ((:) * (Tagged k l v) vs)

# Data

class VariantConstrs xs where Source

Methods

variantConstrs :: DataType -> proxy xs -> [Constr] Source

Instances

 VariantConstrs ([] *) (ShowLabel k l, VariantConstrs xs) => VariantConstrs ((:) * (Tagged k l e) xs)

class GunfoldVariant es v where Source

`implementation of gunfold for Variant`

In ghci

```:set -ddump-deriv -XDeriveDataTypeable
data X a b c = A a | B b | C c deriving (Data,Typeable)```

shows that gunfold is defined something like

```gunfold k z c = case constrIndex c of
1 -> k (z Ghci1.A)
2 -> k (z Ghci1.B)
_ -> k (z Ghci1.C)```

`type X a b c = Variant [Tagged "A" a, Tagged "B" b, Tagged "C" c]`

Then we could write:

```gunfold1 :: (forall b r. Data b => (b -> r) -> c r)
-> Variant [Tagged "A" a, Tagged "B" b, Tagged "C" c]
gunfold1 f c = case constrIndex c of
1 -> f mkA
2 -> f mkB
_ -> f mkC
where mkA a = mkVariant (Label :: Label "A") (a :: a) v
mkB b = mkVariant (Label :: Label "B") (b :: b) v
mkC c = mkVariant (Label :: Label "C") (c :: c) v
v = Proxy :: Proxy [Tagged "A" a, Tagged "B" b, Tagged "C" c]```

where `f = k.z`

Methods

Arguments

 :: (forall b. Data b => (b -> Variant v) -> c (Variant v)) `f = k . z` -> Proxy es -> Int -> c (Variant v)

Instances

 (MkVariant k l e v, Data e, GunfoldVariant ((:) * b bs) v) => GunfoldVariant ((:) * (Tagged k l e) ((:) * b bs)) v (MkVariant k l e v, Data e) => GunfoldVariant ((:) * (Tagged k l e) ([] *)) v

class GfoldlVariant xs xs' where Source

Methods

gfoldlVariant :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Variant xs -> c (Variant xs') Source

the same as `gfoldl`, except the variant that is returned can have more possible values (needed to actually implement gfoldl).

Instances

 (Unvariant ((:) * a ([] *)) v, (~) * a (Tagged k l v), Data v, MkVariant k l v b) => GfoldlVariant ((:) * a ([] *)) b ((~) * a (Tagged k l v), MkVariant k l v r, Data v, GfoldlVariant ((:) * b c) r) => GfoldlVariant ((:) * a ((:) * b c)) r

# Map

newtype HMapV f Source

Apply a function to all possible elements of the variant

Constructors

 HMapV f

Instances

 ((~) * vx (Variant x), (~) * vy (Variant y), HMapAux Variant (HFmap f) x y, SameLength * * x y) => ApplyAB (HMapV f) vx vy apply a function to all values that could be in the variant.

hMapV :: (HMapAux Variant (HFmap f) x y, SameLength' * * y x, SameLength' * * x y) => f -> Variant x -> Variant y Source

shortcut for `applyAB . HMapV`. `hMap` is more general

hMapOutV :: forall x y z f. (SameLength x y, HMapAux Variant (HFmap f) x y, Unvariant y z, HMapOutV_gety x z ~ y) => f -> Variant x -> z Source

`hMapOutV f = unvariant . hMapV f`, except an ambiguous type variable is resolved by `HMapOutV_gety`

type family HMapOutV_gety x z :: [*] Source

resolves an ambiguous type in `hMapOutV`

Instances

 type HMapOutV_gety ([] *) z = [] * type HMapOutV_gety ((:) * (Tagged k s x) xs) z = (:) * (Tagged k s z) (HMapOutV_gety xs z)

# HUpdateAtLabel instance

type HUpdateVariantAtLabelCxt l e v v' n _e = (HFindLabel l v n, HFindLabel l v' n, HUpdateAtHNatR n (Tagged l e) v ~ v', HasField l (Variant v) (Maybe _e), HasField l (Record v') e, MkVariant l e v') Source

# HExtend instance

type family UnMaybe le Source

Instances

 type UnMaybe (Maybe e) = e used for `HExtend` `TIP` type UnMaybe (Tagged k l (Maybe e)) = Tagged k l e

# Conversion to an untagged value

class HAllEqVal x b | x -> b Source

Instances

 HAllEqVal ([] *) True HAllEqVal ((:) * x ([] *)) True (HEq * a a' b, HAllEqVal ((:) * (Tagged k1 t a') xs) b2, (~) Bool (HAnd b b2) b3) => HAllEqVal ((:) * (Tagged k s a) ((:) * (Tagged k t a') xs)) b3

class HAllEqVal' x Source

Instances

 HAllEqVal' ([] *) (HAllEqVal' ((:) * ta xs), (~) * a' a, (~) * ta (Tagged k t a), (~) * ta' (Tagged k1 t' a')) => HAllEqVal' ((:) * ta' ((:) * ta xs)) HAllEqVal' ((:) * x ([] *))

class Unvariant' v e | v -> e where Source

Similar to `unvariant`, except type variables in `v` will be made equal to `e` if possible. That allows the type of `Nothing` to be inferred as `Maybe Char`.

````>>> ````unvariant' \$ x .=. Nothing .*. mkVariant1 y 'y'
```'y'
```

However, this difference leads to more local error messages (`Couldn't match type ‘()’ with ‘Char’`), rather than the following with `unvariant`:

```Fail
'("Variant",
'[Tagged "left" Char, Tagged "right" ()],
"must have all values equal to ",
e))```

Methods

unvariant' :: Variant v -> e Source

Instances

 (HAllEqVal' ((:) * (Tagged * () e) v), Unvariant v e) => Unvariant' v e

class Unvariant v e | v -> e where Source

Convert a Variant which has all possibilities having the same type into a value of that type. Analogous to `either id id`.

See also `unvariant'`

Methods

unvariant :: Variant v -> e Source

Instances

 (Unvariant1 Bool b v e, HAllEqVal v b, HAllEqVal ((:) * (Tagged * () e) v) b) => Unvariant v e

class Unvariant1 b v e | b v -> e where Source

Methods

unvariant1 :: Proxy b -> Variant v -> e Source

Instances

 Fail Symbol "Unvariant applied to empty variant" => Unvariant1 k b ([] *) (Proxy Symbol "Unvariant applied to empty variant") (~) * v (Tagged k t1 e) => Unvariant1 Bool True ((:) * v vs) e Fail * (UnvariantTypeMismatch ((:) * v vs)) => Unvariant1 Bool False ((:) * v vs) (UnvariantTypeMismatch ((:) * v vs))

Instances

 Fail * (UnvariantTypeMismatch ((:) * v vs)) => Unvariant1 Bool False ((:) * v vs) (UnvariantTypeMismatch ((:) * v vs))

unvarianted :: (Unvariant' s a, Unvariant' t b, SameLabels s t, SameLength s t, Functor f) => (a -> f b) -> Variant s -> f (Variant t) Source

`Lens (Variant s) (Variant t) a b`

Analogue of `Control.Lens.chosen :: Lens (Either a a) (Either b b) a b`

unvarianted' :: (HAllEqVal ((:) * (Tagged * () b) s) b1, HAllEqVal s b1, HAllEqVal' ((:) * (Tagged * () b) s), Unvariant1 Bool b1 s b, SameLength' * * s s, SameLabels [*] [*] s s, Functor f) => (b -> f b) -> Variant s -> f (Variant s) Source

`Lens' (Variant s) a`

where we might have `s ~ '[Tagged t1 a, Tagged t2 a]`

# Zip

class ZipVariant x y xy | x y -> xy, xy -> x y where Source

Applies to variants that have the same labels in the same order. A generalization of

```zipEither :: Either a b -> Either a b -> Maybe (Either (a,a) (b,b))
zipEither (Left a) (Left a') = Just (Left (a,a'))
zipEither (Right a) (Right a') = Just (Right (a,a'))
zipEither _ _ = Nothing```

see `HZip` for zipping other collections

Methods

zipVariant :: Variant x -> Variant y -> Maybe (Variant xy) Source

Instances

 ZipVariant ([] *) ([] *) ([] *) ((~) * tx (Tagged k t x), (~) * ty (Tagged k t y), (~) * txy (Tagged k t (x, y)), ZipVariant xs ys zs, MkVariant k t (x, y) ((:) * txy zs)) => ZipVariant ((:) * tx xs) ((:) * ty ys) ((:) * txy zs)

## with a record

class (SameLength v v', SameLabels v v') => ZipVR fs v v' | fs v -> v' where Source

Apply a record of functions to a variant of values. The functions are selected based on those having the same label as the value.

Methods

zipVR_ :: Record fs -> Variant v -> Variant v' Source

`zipVR` is probably a better choice in most situations, since it requires that `fs` has one function for every element of `v`

Instances

 ZipVR fs ([] *) ([] *) ((~) * lv (Tagged k l v), (~) * lv' (Tagged k l v'), HMemberM * (Label k l) (LabelsOf fs) b, HasFieldM k l (Record fs) f, (~) * (DemoteMaybe (v -> v) f) (v -> v'), MkVariant k l v' ((:) * lv' rs), ZipVR fs vs rs) => ZipVR fs ((:) * lv vs) ((:) * lv' rs)

zipVR :: (SameLabels fs v, SameLength fs v, ZipVR fs v v', ZipVRCxt fs v v') => Record fs -> Variant v -> Variant v' Source

````>>> ````let xy = x .*. y .*. emptyProxy
````>>> ````let p = Proxy `asLabelsOf` xy
````>>> ````let vs = [ mkVariant x 1.0 p, mkVariant y () p ]
``````
````>>> ````zipVR (hBuild (+1) id) `map` vs
```[V{x=2.0},V{y=()}]
```

type family ZipVRCxt fs xs ys :: Constraint Source

Lets `zipVR` act as if `ZipVR fs v v'` had an FD `v v' -> fs`

```ZipVRCxt [Tagged s f,  Tagged t g]
[Tagged s fx, Tagged t gx]
[Tagged s fy, Tagged t gy]
= (f ~ (fx -> fy), g ~ (gx -> gy))```

Instances

 type ZipVRCxt ([] *) ([] *) ([] *) = () type ZipVRCxt ((:) * (Tagged k s f) fs) ((:) * (Tagged k s x) xs) ((:) * (Tagged k s y) ys) = ((~) * f (x -> y), ZipVRCxt fs xs ys)

# Eq

## Alternative Eq

eqVariant :: (HAllEqVal ((:) * (Tagged * () Bool) (HMapOutV_gety x Bool)) b, HAllEqVal (HMapOutV_gety x Bool) b, Unvariant1 Bool b (HMapOutV_gety x Bool) Bool, ZipVariant x1 y x, HMapAux Variant (HFmap UncurryEq) x (HMapOutV_gety x Bool), SameLength' * * (HMapOutV_gety x Bool) x, SameLength' * * x (HMapOutV_gety x Bool)) => Variant x1 -> Variant y -> Bool Source

implemented like `and (zipWith (==) xs ys)`. Behaves the same as the Eq instances for `Variant`

data UncurryEq Source

Constructors

 UncurryEq

Instances

 ((~) * ee (e, e), Eq e, (~) * bool Bool) => ApplyAB UncurryEq ee bool

# Projection

class ProjectVariant x y where Source

convert a variant with more fields into one with fewer (or the same) fields.

````>>> ````let ty = Proxy :: Proxy [Tagged "left" Int, Tagged "right" Int]
````>>> ````let l = mkVariant _left 1 ty
````>>> ````let r = mkVariant _right 2 ty
``````
````>>> ````map projectVariant [l, r] :: [Maybe (Variant '[Tagged "left" Int])]
```[Just V{left=1},Nothing]
```

`rearrangeVariant = fromJust . projectVariant` is one implementation of `rearrangeVariant`, since the result can have the same fields with a different order:

````>>> ````let yt = Proxy :: Proxy [Tagged "right" Int, Tagged "left" Int]
``````
````>>> ````map projectVariant [l, r] `asTypeOf` [Just (mkVariant _left 0 yt)]
```[Just V{left=1},Just V{right=2}]
```

Methods

Instances

 ProjectVariant x ([] *) (ProjectVariant x ys, HasField k t (Variant x) (Maybe y), HOccursNot * (Label k t) (LabelsOf ys), (~) * ty (Tagged k t y)) => ProjectVariant x ((:) * ty ys)

class HAllTaggedLV y => ProjectExtendVariant x y where Source

`projectExtendVariant = fmap `extendVariant` . `projectVariant``

where intermediate variant is as large as possible. Used to implement Data.HList.Labelable.`projected`

Note that:

````>>> ````let r = projectExtendVariant (mkVariant1 Label 1 :: Variant '[Tagged "x" Int])
````>>> ````r :: Maybe (Variant '[Tagged "x" Integer])
```Nothing
```

Methods

Instances

 HAllTaggedLV y => ProjectExtendVariant ([] *) y ((~) * lv (Tagged k l v), HMemberM * lv y inY, ProjectExtendVariant' inY lv y, ProjectExtendVariant xs y) => ProjectExtendVariant ((:) * lv xs) y

class ProjectExtendVariant' inY lv y where Source

Methods

projectExtendVariant' :: Proxy inY -> lv -> Maybe (Variant y) Source

Instances

 ProjectExtendVariant' (Nothing [*]) lv y (MkVariant k l v y, (~) * lv (Tagged k l v)) => ProjectExtendVariant' (Just [*] t) lv y

class (ProjectVariant x yin, ProjectVariant x yout) => SplitVariant x yin yout where Source

Methods

splitVariant :: Variant x -> Either (Variant yin) (Variant yout) Source

Instances

 (ProjectVariant x yin, ProjectVariant x yout, H2ProjectByLabels (LabelsOf yin) x xi xo, HRearrange (LabelsOf yin) xi yin, HRearrange (LabelsOf yout) xo yout, HLeftUnion xi xo xixo, HRearrange (LabelsOf x) xixo x, HAllTaggedLV x, HAllTaggedLV yin, HAllTaggedLV yout) => SplitVariant x yin yout

class (HAllTaggedLV y, HAllTaggedLV x) => ExtendsVariant x y where Source

`projectVariant . extendsVariant = Just` (when the types match up)

`extendVariant` is a special case

Methods

Instances

 (HAllTaggedLV x, Unvariant ((:) * le ([] *)) e, MkVariant k l e x, (~) * le (Tagged k l e)) => ExtendsVariant ((:) * le ([] *)) x (MkVariant k l e y, (~) * le (Tagged k l e), ExtendsVariant ((:) * b bs) y) => ExtendsVariant ((:) * le ((:) * b bs)) y

rearrangeVariant :: (SameLength v v', ExtendsVariant v v') => Variant v -> Variant v' Source

`rearrangeVariant` is a specialization of `extendsVariant` whose result is always . see also `rearranged`

hMaybied :: (VariantToHMaybied v1 x, VariantToHMaybied v r, HFoldr HMaybiedToVariantFs [Variant ([] *)] x [Variant v1], HMapAux HList (HFmap HCastF) x r, SameLength' * * x r, SameLength' * * r x, Choice p, Applicative f) => p (Variant v1) (f (Variant v)) -> p (Record x) (f (Record r)) Source

`Prism (Record tma) (Record tmb) (Variant ta) (Variant tb)`

see `hMaybied'`

data HCastF Source

Constructors

 HCastF

Instances

 ((~) * mx (Maybe x), (~) * my (Maybe y), HCast y x) => ApplyAB HCastF mx my

hMaybied' :: (VariantToHMaybied v x, HFoldr HMaybiedToVariantFs [Variant ([] *)] x [Variant v], HMapAux HList (HFmap HCastF) x x, SameLength' * * x x, Choice p, Applicative f) => p (Variant v) (f (Variant v)) -> p (Record x) (f (Record x)) Source

`Prism' (Record tma) (Variant ta)`

where `tma` and `tmb` are lists like

```tma ~ '[Tagged x (Maybe a), Tagged y (Maybe b)]
ta  ~ '[Tagged x        a , Tagged y        b ]```

If one element of the record is Just, the Variant will contain that element. Otherwise, the prism fails.

`Note`

The types work out to define a prism:

`l = `prism'` `variantToHMaybied` (`listToMaybe` . `hMaybiedToVariants`)`

but the law: `s^?l ≡ Just a ==> l # a ≡ s` is not followed, because we could have:

```  s, s2 :: Record '[Tagged "x" (Maybe Int), Tagged "y" (Maybe Char)]
s = hBuild (Just 1) (Just '2')
s2 = hBuild (Just 1) Nothing

v :: Variant '[Tagged "x" Int, Tagged "y" Char]
v = mkVariant (Label :: Label "x") 1 Proxy
```

So that `s^?l == Just v`. But `l#v == s2 /= s`, while the law requires `l#v == s`. hMaybied avoids this problem by only producing a value when there is only one present.

class VariantToHMaybied v r | v -> r, r -> v where Source

Methods

Instances

 VariantToHMaybied ([] *) ([] *) (VariantToHMaybied v r, HReplicateF nr ConstTaggedNothing () r, (~) * tx (Tagged k t x), (~) * tmx (Tagged k t (Maybe x))) => VariantToHMaybied ((:) * tx v) ((:) * tmx r)

Constructors

 ConstTaggedNothing

Instances

 (~) * y (Tagged k t (Maybe e)) => ApplyAB ConstTaggedNothing x y

hMaybiedToVariants :: (HFoldr HMaybiedToVariantFs [Variant []] r [Variant v], VariantToHMaybied v r) => Record r -> [Variant v] Source

Every element of the record that is Just becomes one element in the resulting list. See `hMaybied'` example types that `r` and `v` can take.

Constructors

 HMaybiedToVariantFs

Instances

 ((~) * x (Tagged k t (Maybe e), [Variant v]), (~) * y [Variant ((:) * (Tagged k t e) v)], MkVariant k t e ((:) * (Tagged k t e) v)) => ApplyAB HMaybiedToVariantFs x y