HList-0.5.2.0: Heterogeneous lists
Safe HaskellNone
LanguageHaskell2010

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

Instances details
Relabeled Variant Source # 
Instance details

Defined in Data.HList.Variant

Methods

relabeled :: forall p f (s :: [Type]) (t :: [Type]) (a :: [Type]) (b :: [Type]). (HMapTaggedFn (RecordValuesR s) a, HMapTaggedFn (RecordValuesR b) t, SameLengths '[s, a, t, b], RecordValuesR t ~ RecordValuesR b, RecordValuesR s ~ RecordValuesR a, RecordValues b, RecordValues s, Profunctor p, Functor f) => p (Variant a) (f (Variant b)) -> p (Variant s) (f (Variant t)) Source #

TypeIndexed Variant TIC Source # 
Instance details

Defined in Data.HList.TIC

Methods

typeIndexed :: forall p f (s :: [Type]) (t :: [Type]) (a :: [Type]) (b :: [Type]). (TypeIndexedCxt s t a b, Profunctor p, Functor f) => p (TIC (TagR a)) (f (TIC (TagR b))) -> p (Variant s) (f (Variant t)) Source #

(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 Source #
Prism (Variant s) (Variant t) (Variant a) (Variant b)
Instance details

Defined in Data.HList.Labelable

Methods

projected :: forall (ty :: LabeledOpticType) p f. (ty ~ LabelableTy Variant, LabeledOpticP ty p, LabeledOpticF ty f) => p (Variant a) (f (Variant b)) -> p (Variant s) (f (Variant t)) Source #

HUpdateVariantAtLabelCxt l e v v' n _e => HUpdateAtLabel Variant (l :: k) e v v' Source #
hUpdateAtLabel x e' (mkVariant x e proxy) == mkVariant x e' proxy
hUpdateAtLabel y e' (mkVariant x e proxy) == mkVariant x e  proxy
Instance details

Defined in Data.HList.Variant

Methods

hUpdateAtLabel :: Label l -> e -> Variant v -> Variant v' Source #

(HPrism x s t a b, to ~ ((->) :: Type -> Type -> Type)) => Labelable (x :: k) Variant s t a b Source #

make a Prism (Variant s) (Variant t) a b

Instance details

Defined in Data.HList.Labelable

Associated Types

type LabelableTy Variant :: LabeledOpticType Source #

Methods

hLens' :: Label x -> LabeledOptic x Variant s t a b Source #

(HasField x (Record vs) a, HFindLabel x vs n, HNat2Integral n) => HasField (x :: k) (Variant vs) (Maybe a) Source # 
Instance details

Defined in Data.HList.Variant

Methods

hLookupByLabel :: Label x -> Variant vs -> Maybe a Source #

(ApplyAB f te te', HMapCxt Variant f (l ': ls) (l' ': ls')) => HMapAux Variant f (te ': (l ': ls)) (te' ': (l' ': ls')) Source # 
Instance details

Defined in Data.HList.Variant

Methods

hMapAux :: f -> Variant (te ': (l ': ls)) -> Variant (te' ': (l' ': ls')) Source #

ApplyAB f te te' => HMapAux Variant f '[te] '[te'] Source # 
Instance details

Defined in Data.HList.Variant

Methods

hMapAux :: f -> Variant '[te] -> Variant '[te'] Source #

(le ~ Tagged l (Maybe e), HOccursNot (Label l) (LabelsOf v)) => HExtend le (Variant v) Source #

Extension for Variants prefers the first value

(l .=. Nothing) .*. v = v
(l .=. Just e)  .*. _ = mkVariant l e Proxy
Instance details

Defined in Data.HList.Variant

Associated Types

type HExtendR le (Variant v) Source #

Methods

(.*.) :: le -> Variant v -> HExtendR le (Variant v) Source #

(HasField l (Variant r) (Maybe u), HasFieldPath 'True ls u (Maybe v)) => HasFieldPath needJust (Label l ': ls) (Variant r) (Maybe v) Source # 
Instance details

Defined in Data.HList.Dredge

Methods

hLookupByLabelPath1 :: Proxy needJust -> Label (Label l ': ls) -> Variant r -> Maybe v Source #

(Unvariant '[txy] txy, tx ~ Tagged t x, ty ~ Tagged t y, txy ~ Tagged t (x, y)) => HUnzip Variant '[tx] '[ty] '[txy] Source # 
Instance details

Defined in Data.HList.Variant

Methods

hUnzip :: Variant '[txy] -> (Variant '[tx], Variant '[ty]) Source #

(HUnzip Variant (x2 ': xs) (y2 ': ys) (xy2 ': xys), SameLength xs ys, SameLength ys xys, tx ~ Tagged t x, ty ~ Tagged t y, txy ~ Tagged t (x, y)) => HUnzip Variant (tx ': (x2 ': xs)) (ty ': (y2 ': ys)) (txy ': (xy2 ': xys)) Source # 
Instance details

Defined in Data.HList.Variant

Methods

hUnzip :: Variant (txy ': (xy2 ': xys)) -> (Variant (tx ': (x2 ': xs)), Variant (ty ': (y2 ': ys))) Source #

(Bounded x, Bounded z, HRevAppR (Tagged s x ': xs) ('[] :: [Type]) ~ (Tagged t z ': sx), MkVariant t z (Tagged s x ': xs)) => Bounded (Variant (Tagged s x ': xs)) Source # 
Instance details

Defined in Data.HList.Variant

Methods

minBound :: Variant (Tagged s x ': xs) #

maxBound :: Variant (Tagged s x ': xs) #

Enum x => Enum (Variant '[Tagged s x]) Source #

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.

Instance details

Defined in Data.HList.Variant

Methods

succ :: Variant '[Tagged s x] -> Variant '[Tagged s x] #

pred :: Variant '[Tagged s x] -> Variant '[Tagged s x] #

toEnum :: Int -> Variant '[Tagged s x] #

fromEnum :: Variant '[Tagged s x] -> Int #

enumFrom :: Variant '[Tagged s x] -> [Variant '[Tagged s x]] #

enumFromThen :: Variant '[Tagged s x] -> Variant '[Tagged s x] -> [Variant '[Tagged s x]] #

enumFromTo :: Variant '[Tagged s x] -> Variant '[Tagged s x] -> [Variant '[Tagged s x]] #

enumFromThenTo :: Variant '[Tagged s x] -> Variant '[Tagged s x] -> Variant '[Tagged s x] -> [Variant '[Tagged s x]] #

(Enum x, Bounded x, Enum (Variant (y ': z))) => Enum (Variant (Tagged s x ': (y ': z))) Source #
>>> 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}]
Instance details

Defined in Data.HList.Variant

Methods

succ :: Variant (Tagged s x ': (y ': z)) -> Variant (Tagged s x ': (y ': z)) #

pred :: Variant (Tagged s x ': (y ': z)) -> Variant (Tagged s x ': (y ': z)) #

toEnum :: Int -> Variant (Tagged s x ': (y ': z)) #

fromEnum :: Variant (Tagged s x ': (y ': z)) -> Int #

enumFrom :: Variant (Tagged s x ': (y ': z)) -> [Variant (Tagged s x ': (y ': z))] #

enumFromThen :: Variant (Tagged s x ': (y ': z)) -> Variant (Tagged s x ': (y ': z)) -> [Variant (Tagged s x ': (y ': z))] #

enumFromTo :: Variant (Tagged s x ': (y ': z)) -> Variant (Tagged s x ': (y ': z)) -> [Variant (Tagged s x ': (y ': z))] #

enumFromThenTo :: Variant (Tagged s x ': (y ': z)) -> Variant (Tagged s x ': (y ': z)) -> Variant (Tagged s x ': (y ': z)) -> [Variant (Tagged s x ': (y ': z))] #

(Eq (Variant xs), Eq x) => Eq (Variant (x ': xs)) Source # 
Instance details

Defined in Data.HList.Variant

Methods

(==) :: Variant (x ': xs) -> Variant (x ': xs) -> Bool #

(/=) :: Variant (x ': xs) -> Variant (x ': xs) -> Bool #

Eq (Variant ('[] :: [Type])) Source # 
Instance details

Defined in Data.HList.Variant

Methods

(==) :: Variant '[] -> Variant '[] -> Bool #

(/=) :: Variant '[] -> Variant '[] -> Bool #

(Typeable (Variant v), GfoldlVariant v v, GunfoldVariant v v, VariantConstrs v) => Data (Variant v) Source # 
Instance details

Defined in Data.HList.Variant

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Variant v -> c (Variant v) #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Variant v) #

toConstr :: Variant v -> Constr #

dataTypeOf :: Variant v -> DataType #

dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (Variant v)) #

dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Variant v)) #

gmapT :: (forall b. Data b => b -> b) -> Variant v -> Variant v #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Variant v -> r #

gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Variant v -> r #

gmapQ :: (forall d. Data d => d -> u) -> Variant v -> [u] #

gmapQi :: Int -> (forall d. Data d => d -> u) -> Variant v -> u #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> Variant v -> m (Variant v) #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Variant v -> m (Variant v) #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Variant v -> m (Variant v) #

(Ord x, Ord (Variant xs)) => Ord (Variant (x ': xs)) Source # 
Instance details

Defined in Data.HList.Variant

Methods

compare :: Variant (x ': xs) -> Variant (x ': xs) -> Ordering #

(<) :: Variant (x ': xs) -> Variant (x ': xs) -> Bool #

(<=) :: Variant (x ': xs) -> Variant (x ': xs) -> Bool #

(>) :: Variant (x ': xs) -> Variant (x ': xs) -> Bool #

(>=) :: Variant (x ': xs) -> Variant (x ': xs) -> Bool #

max :: Variant (x ': xs) -> Variant (x ': xs) -> Variant (x ': xs) #

min :: Variant (x ': xs) -> Variant (x ': xs) -> Variant (x ': xs) #

Ord (Variant ('[] :: [Type])) Source # 
Instance details

Defined in Data.HList.Variant

Methods

compare :: Variant '[] -> Variant '[] -> Ordering #

(<) :: Variant '[] -> Variant '[] -> Bool #

(<=) :: Variant '[] -> Variant '[] -> Bool #

(>) :: Variant '[] -> Variant '[] -> Bool #

(>=) :: Variant '[] -> Variant '[] -> Bool #

max :: Variant '[] -> Variant '[] -> Variant '[] #

min :: Variant '[] -> Variant '[] -> Variant '[] #

ReadVariant v => Read (Variant v) Source #

A corresponding read instance

Instance details

Defined in Data.HList.Variant

ShowVariant vs => Show (Variant vs) Source #

Variants are not opaque

Instance details

Defined in Data.HList.Variant

Methods

showsPrec :: Int -> Variant vs -> ShowS #

show :: Variant vs -> String #

showList :: [Variant vs] -> ShowS #

(Semigroup x, Semigroup (Variant (a ': b))) => Semigroup (Variant (Tagged t x ': (a ': b))) Source # 
Instance details

Defined in Data.HList.Variant

Methods

(<>) :: Variant (Tagged t x ': (a ': b)) -> Variant (Tagged t x ': (a ': b)) -> Variant (Tagged t x ': (a ': b)) #

sconcat :: NonEmpty (Variant (Tagged t x ': (a ': b))) -> Variant (Tagged t x ': (a ': b)) #

stimes :: Integral b0 => b0 -> Variant (Tagged t x ': (a ': b)) -> Variant (Tagged t x ': (a ': b)) #

(Unvariant '[Tagged t x] x, Semigroup x) => Semigroup (Variant '[Tagged t x]) Source # 
Instance details

Defined in Data.HList.Variant

Methods

(<>) :: Variant '[Tagged t x] -> Variant '[Tagged t x] -> Variant '[Tagged t x] #

sconcat :: NonEmpty (Variant '[Tagged t x]) -> Variant '[Tagged t x] #

stimes :: Integral b => b -> Variant '[Tagged t x] -> Variant '[Tagged t x] #

(Monoid x, Monoid (Variant (a ': b))) => Monoid (Variant (Tagged t x ': (a ': b))) Source # 
Instance details

Defined in Data.HList.Variant

Methods

mempty :: Variant (Tagged t x ': (a ': b)) #

mappend :: Variant (Tagged t x ': (a ': b)) -> Variant (Tagged t x ': (a ': b)) -> Variant (Tagged t x ': (a ': b)) #

mconcat :: [Variant (Tagged t x ': (a ': b))] -> Variant (Tagged t x ': (a ': b)) #

(Unvariant '[Tagged t x] x, Monoid x) => Monoid (Variant '[Tagged t x]) Source # 
Instance details

Defined in Data.HList.Variant

Methods

mempty :: Variant '[Tagged t x] #

mappend :: Variant '[Tagged t x] -> Variant '[Tagged t x] -> Variant '[Tagged t x] #

mconcat :: [Variant '[Tagged t x]] -> Variant '[Tagged t x] #

(SameLength s a, ExtendsVariant s a, SameLength b t, ExtendsVariant b t) => Rearranged Variant (s :: [Type]) (t :: [Type]) (a :: [Type]) (b :: [Type]) Source # 
Instance details

Defined in Data.HList.Variant

Methods

rearranged :: (Profunctor p, Functor f) => p (Variant a) (f (Variant b)) -> p (Variant s) (f (Variant t)) Source #

type LabelableTy Variant Source # 
Instance details

Defined in Data.HList.Labelable

type HExtendR le (Variant v) Source # 
Instance details

Defined in Data.HList.Variant

type HExtendR le (Variant v) = Variant (UnMaybe le ': v)

Unsafe operations

unsafeMkVariant Source #

Arguments

:: Int

n

-> v 
-> Variant vs 

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

unsafeCastVariant :: Variant v -> Variant v' Source #

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

unsafeEmptyVariant :: Variant '[] Source #

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

mkVariant Source #

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

Instances details
(HFindLabel x vs n, HNat2Integral n, HasField x (Variant vs) (Maybe v)) => MkVariant (x :: k) v vs Source # 
Instance details

Defined in Data.HList.Variant

Methods

mkVariant :: Label x -> v -> proxy vs -> Variant vs Source #

mkVariant1 :: forall k (l :: k) e. Label l -> e -> Variant '[Tagged 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 (Tagged s x ': xs) -> Either x (Variant xs) Source #

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

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

Defined in Data.HList.Variant

Methods

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

Read

class ShowVariant vs where Source #

helper class for defining the Show instance

Methods

showVariant :: Variant vs -> ShowS Source #

Instances

Instances details
(ShowLabel l, Show v, lv ~ Tagged l v) => ShowVariant '[lv] Source # 
Instance details

Defined in Data.HList.Variant

Methods

showVariant :: Variant '[lv] -> ShowS Source #

(ShowLabel l, Show v, ShowVariant (w ': ws)) => ShowVariant (Tagged l v ': (w ': ws)) Source # 
Instance details

Defined in Data.HList.Variant

Methods

showVariant :: Variant (Tagged l v ': (w ': ws)) -> ShowS Source #

Show

class ReadVariant vs where Source #

Instances

Instances details
ReadVariant ('[] :: [Type]) Source # 
Instance details

Defined in Data.HList.Variant

Methods

readVariant :: ReadP (Variant '[]) Source #

(ShowLabel l, Read v, ReadVariant vs, HOccursNot (Label l) (LabelsOf vs)) => ReadVariant (Tagged l v ': vs) Source # 
Instance details

Defined in Data.HList.Variant

Methods

readVariant :: ReadP (Variant (Tagged l v ': vs)) Source #

Data

class VariantConstrs (xs :: [*]) where Source #

Methods

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

Instances

Instances details
VariantConstrs ('[] :: [Type]) Source # 
Instance details

Defined in Data.HList.Variant

Methods

variantConstrs :: DataType -> proxy '[] -> [Constr] Source #

(ShowLabel l, VariantConstrs xs) => VariantConstrs (Tagged l e ': xs) Source # 
Instance details

Defined in Data.HList.Variant

Methods

variantConstrs :: DataType -> proxy (Tagged l e ': xs) -> [Constr] Source #

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)

If we instead had

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

gunfoldVariant Source #

Arguments

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

Instances

Instances details
(MkVariant l e v, Data e, GunfoldVariant (b ': bs) v) => GunfoldVariant (Tagged l e ': (b ': bs)) v Source # 
Instance details

Defined in Data.HList.Variant

Methods

gunfoldVariant :: (forall b0. Data b0 => (b0 -> Variant v) -> c (Variant v)) -> Proxy (Tagged l e ': (b ': bs)) -> Int -> c (Variant v) Source #

(MkVariant l e v, Data e) => GunfoldVariant '[Tagged l e] v Source # 
Instance details

Defined in Data.HList.Variant

Methods

gunfoldVariant :: (forall b. Data b => (b -> Variant v) -> c (Variant v)) -> Proxy '[Tagged l e] -> Int -> c (Variant v) Source #

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

Instances details
(Unvariant '[a] v, a ~ Tagged l v, Data v, MkVariant l v b) => GfoldlVariant '[a] b Source # 
Instance details

Defined in Data.HList.Variant

Methods

gfoldlVariant :: (forall d b0. Data d => c (d -> b0) -> d -> c b0) -> (forall g. g -> c g) -> Variant '[a] -> c (Variant b) Source #

(a ~ Tagged l v, MkVariant l v r, Data v, GfoldlVariant (b ': c) r) => GfoldlVariant (a ': (b ': c)) r Source # 
Instance details

Defined in Data.HList.Variant

Methods

gfoldlVariant :: (forall d b0. Data d => c0 (d -> b0) -> d -> c0 b0) -> (forall g. g -> c0 g) -> Variant (a ': (b ': c)) -> c0 (Variant r) Source #

Map

newtype HMapV f Source #

Apply a function to all possible elements of the variant

Constructors

HMapV f 

Instances

Instances details
(vx ~ Variant x, vy ~ Variant y, HMapAux Variant (HFmap f) x y, SameLength x y) => ApplyAB (HMapV f) vx vy Source #

apply a function to all values that could be in the variant.

Instance details

Defined in Data.HList.Variant

Methods

applyAB :: HMapV f -> vx -> vy Source #

hMapV :: forall f (x :: [Type]) (y :: [Type]). (HMapAux Variant (HFmap f) x y, SameLength' x y, SameLength' y x) => 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

Instances details
type HMapOutV_gety ('[] :: [Type]) z Source # 
Instance details

Defined in Data.HList.Variant

type HMapOutV_gety ('[] :: [Type]) z = '[] :: [Type]
type HMapOutV_gety (Tagged s x ': xs) z Source # 
Instance details

Defined in Data.HList.Variant

type HMapOutV_gety (Tagged s x ': xs) z = Tagged 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

Instances details
type UnMaybe (Maybe e) Source #

used for HExtend TIP

Instance details

Defined in Data.HList.Variant

type UnMaybe (Maybe e) = e
type UnMaybe (Tagged l (Maybe e)) Source # 
Instance details

Defined in Data.HList.Variant

type UnMaybe (Tagged l (Maybe e)) = Tagged l e

Conversion to an untagged value

class HAllEqVal (x :: [*]) (b :: Bool) | x -> b Source #

Instances

Instances details
HAllEqVal ('[] :: [Type]) 'True Source # 
Instance details

Defined in Data.HList.Variant

HAllEqVal '[x] 'True Source # 
Instance details

Defined in Data.HList.Variant

(HEq a a' b, HAllEqVal (Tagged t a' ': xs) b2, HAnd b b2 ~ b3) => HAllEqVal (Tagged s a ': (Tagged t a' ': xs)) b3 Source # 
Instance details

Defined in Data.HList.Variant

class HAllEqVal' (x :: [*]) Source #

Instances

Instances details
HAllEqVal' ('[] :: [Type]) Source # 
Instance details

Defined in Data.HList.Variant

(HAllEqVal' (ta ': xs), a' ~ a, ta ~ Tagged t a, ta' ~ Tagged t' a') => HAllEqVal' (ta' ': (ta ': xs)) Source # 
Instance details

Defined in Data.HList.Variant

HAllEqVal' '[x] Source # 
Instance details

Defined in Data.HList.Variant

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

Instances details
(HAllEqVal' (Tagged () e ': v), Unvariant v e) => Unvariant' v e Source # 
Instance details

Defined in Data.HList.Variant

Methods

unvariant' :: Variant v -> e Source #

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

Instances details
(Unvariant1 b v e, HAllEqVal v b, HAllEqVal (Tagged () e ': v) b) => Unvariant v e Source # 
Instance details

Defined in Data.HList.Variant

Methods

unvariant :: Variant v -> e Source #

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

Methods

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

Instances

Instances details
Fail "Unvariant applied to empty variant" => Unvariant1 (b :: k) ('[] :: [Type]) (Proxy "Unvariant applied to empty variant") Source # 
Instance details

Defined in Data.HList.Variant

Methods

unvariant1 :: Proxy b -> Variant '[] -> Proxy "Unvariant applied to empty variant" Source #

v ~ Tagged t1 e => Unvariant1 'True (v ': vs) e Source # 
Instance details

Defined in Data.HList.Variant

Methods

unvariant1 :: Proxy 'True -> Variant (v ': vs) -> e Source #

Fail (UnvariantTypeMismatch (v ': vs)) => Unvariant1 'False (v ': vs) (UnvariantTypeMismatch (v ': vs)) Source # 
Instance details

Defined in Data.HList.Variant

Methods

unvariant1 :: Proxy 'False -> Variant (v ': vs) -> UnvariantTypeMismatch (v ': vs) Source #

data UnvariantTypeMismatch (vs :: [*]) Source #

Instances

Instances details
Fail (UnvariantTypeMismatch (v ': vs)) => Unvariant1 'False (v ': vs) (UnvariantTypeMismatch (v ': vs)) Source # 
Instance details

Defined in Data.HList.Variant

Methods

unvariant1 :: Proxy 'False -> Variant (v ': vs) -> UnvariantTypeMismatch (v ': vs) Source #

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' :: forall (b :: Bool) (t :: [Type]) a f. (Unvariant1 b t a, HAllEqVal' (Tagged () a ': t), HAllEqVal t b, HAllEqVal (Tagged () a ': t) b, SameLabels t t, SameLength' t t, Functor f) => (a -> f a) -> Variant t -> f (Variant t) 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

Instances details
ZipVariant ('[] :: [Type]) ('[] :: [Type]) ('[] :: [Type]) Source # 
Instance details

Defined in Data.HList.Variant

Methods

zipVariant :: Variant '[] -> Variant '[] -> Maybe (Variant '[]) Source #

(tx ~ Tagged t x, ty ~ Tagged t y, txy ~ Tagged t (x, y), ZipVariant xs ys zs, MkVariant t (x, y) (txy ': zs)) => ZipVariant (tx ': xs) (ty ': ys) (txy ': zs) Source # 
Instance details

Defined in Data.HList.Variant

Methods

zipVariant :: Variant (tx ': xs) -> Variant (ty ': ys) -> Maybe (Variant (txy ': zs)) Source #

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

Instances details
ZipVR fs ('[] :: [Type]) ('[] :: [Type]) Source # 
Instance details

Defined in Data.HList.Variant

Methods

zipVR_ :: Record fs -> Variant '[] -> Variant '[] Source #

(lv ~ Tagged l v, lv' ~ Tagged l v', HMemberM (Label l) (LabelsOf fs) b, HasFieldM l (Record fs) f, DemoteMaybe (v -> v) f ~ (v -> v'), MkVariant l v' (lv' ': rs), ZipVR fs vs rs) => ZipVR fs (lv ': vs) (lv' ': rs) Source # 
Instance details

Defined in Data.HList.Variant

Methods

zipVR_ :: Record fs -> Variant (lv ': vs) -> Variant (lv' ': rs) Source #

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

Instances details
type ZipVRCxt ('[] :: [Type]) ('[] :: [Type]) ('[] :: [Type]) Source # 
Instance details

Defined in Data.HList.Variant

type ZipVRCxt ('[] :: [Type]) ('[] :: [Type]) ('[] :: [Type]) = ()
type ZipVRCxt (Tagged s f ': fs) (Tagged s x ': xs) (Tagged s y ': ys) Source # 
Instance details

Defined in Data.HList.Variant

type ZipVRCxt (Tagged s f ': fs) (Tagged s x ': xs) (Tagged s y ': ys) = (f ~ (x -> y), ZipVRCxt fs xs ys)

Eq

Alternative Eq

eqVariant :: forall (x1 :: [Type]) (b :: Bool) (x2 :: [Type]) (y :: [Type]). (SameLength' x1 (HMapOutV_gety x1 Bool), SameLength' (HMapOutV_gety x1 Bool) x1, HMapAux Variant (HFmap UncurryEq) x1 (HMapOutV_gety x1 Bool), Unvariant1 b (HMapOutV_gety x1 Bool) Bool, HAllEqVal (HMapOutV_gety x1 Bool) b, HAllEqVal (Tagged () Bool ': HMapOutV_gety x1 Bool) b, ZipVariant x2 y x1) => Variant x2 -> 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

Instances details
(ee ~ (e, e), Eq e, bool ~ Bool) => ApplyAB UncurryEq ee bool Source # 
Instance details

Defined in Data.HList.Variant

Methods

applyAB :: UncurryEq -> ee -> bool Source #

Ord

Bounded

Enum

Ix (TODO)

Semigroup

Monoid

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}]

Instances

Instances details
ProjectVariant x ('[] :: [Type]) Source # 
Instance details

Defined in Data.HList.Variant

(ProjectVariant x ys, HasField t (Variant x) (Maybe y), HOccursNot (Label t) (LabelsOf ys), ty ~ Tagged t y) => ProjectVariant x (ty ': ys) Source # 
Instance details

Defined in Data.HList.Variant

Methods

projectVariant :: Variant x -> Maybe (Variant (ty ': ys)) Source #

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

Instances

Instances details
HAllTaggedLV y => ProjectExtendVariant ('[] :: [Type]) y Source # 
Instance details

Defined in Data.HList.Variant

(lv ~ Tagged l v, HMemberM lv y inY, ProjectExtendVariant' inY lv y, ProjectExtendVariant xs y) => ProjectExtendVariant (lv ': xs) y Source # 
Instance details

Defined in Data.HList.Variant

Methods

projectExtendVariant :: Variant (lv ': xs) -> Maybe (Variant y) Source #

class ProjectExtendVariant' (inY :: Maybe [*]) lv (y :: [*]) where Source #

Methods

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

Instances

Instances details
ProjectExtendVariant' ('Nothing :: Maybe [Type]) lv y Source # 
Instance details

Defined in Data.HList.Variant

(MkVariant l v y, lv ~ Tagged l v) => ProjectExtendVariant' ('Just t) lv y Source # 
Instance details

Defined in Data.HList.Variant

Methods

projectExtendVariant' :: Proxy ('Just t) -> lv -> Maybe (Variant y) Source #

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

Methods

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

Instances

Instances details
(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 Source # 
Instance details

Defined in Data.HList.Variant

Methods

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

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

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

extendVariant is a special case

Instances

Instances details
(HAllTaggedLV x, Unvariant '[le] e, MkVariant l e x, le ~ Tagged l e) => ExtendsVariant '[le] x Source # 
Instance details

Defined in Data.HList.Variant

Methods

extendsVariant :: Variant '[le] -> Variant x Source #

(MkVariant l e y, le ~ Tagged l e, ExtendsVariant (b ': bs) y) => ExtendsVariant (le ': (b ': bs)) y Source # 
Instance details

Defined in Data.HList.Variant

Methods

extendsVariant :: Variant (le ': (b ': bs)) -> Variant y Source #

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 :: forall (x :: [Type]) (v1 :: [Type]) (v2 :: [Type]) (r :: [Type]) p f. (HFoldr HMaybiedToVariantFs [Variant ('[] :: [Type])] x [Variant v1], VariantToHMaybied v2 r, VariantToHMaybied v1 x, SameLength' x r, SameLength' r x, HMapAux HList (HFmap HCastF) x r, Choice p, Applicative f) => p (Variant v1) (f (Variant v2)) -> p (Record x) (f (Record r)) Source #

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

see hMaybied'

data HCastF Source #

Constructors

HCastF 

Instances

Instances details
(mx ~ Maybe x, my ~ Maybe y, HCast y x) => ApplyAB HCastF mx my Source # 
Instance details

Defined in Data.HList.Variant

Methods

applyAB :: HCastF -> mx -> my Source #

hMaybied' :: forall (x :: [Type]) (v :: [Type]) p f. (HFoldr HMaybiedToVariantFs [Variant ('[] :: [Type])] x [Variant v], VariantToHMaybied v x, SameLength' x x, HMapAux HList (HFmap HCastF) 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 #

Instances

Instances details
VariantToHMaybied ('[] :: [Type]) ('[] :: [Type]) Source # 
Instance details

Defined in Data.HList.Variant

Methods

variantToHMaybied :: Variant '[] -> Record '[] Source #

(VariantToHMaybied v r, HReplicateF nr ConstTaggedNothing () r, tx ~ Tagged t x, tmx ~ Tagged t (Maybe x)) => VariantToHMaybied (tx ': v) (tmx ': r) Source # 
Instance details

Defined in Data.HList.Variant

Methods

variantToHMaybied :: Variant (tx ': v) -> Record (tmx ': r) Source #

data ConstTaggedNothing Source #

Constructors

ConstTaggedNothing 

Instances

Instances details
y ~ Tagged t (Maybe e) => ApplyAB ConstTaggedNothing x y Source # 
Instance details

Defined in Data.HList.Variant

Methods

applyAB :: ConstTaggedNothing -> x -> y Source #

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.

data HMaybiedToVariantFs Source #

Constructors

HMaybiedToVariantFs 

Instances

Instances details
(x ~ (Tagged t (Maybe e), [Variant v]), y ~ [Variant (Tagged t e ': v)], MkVariant t e (Tagged t e ': v)) => ApplyAB HMaybiedToVariantFs x y Source # 
Instance details

Defined in Data.HList.Variant

Methods

applyAB :: HMaybiedToVariantFs -> x -> y Source #