Safe Haskell | None |
---|---|
Language | Haskell2010 |
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
- data Variant (vs :: [*]) = Variant !Int Any
- unsafeMkVariant :: Int -> v -> Variant vs
- unsafeCastVariant :: Variant v -> Variant v'
- castVariant :: (RecordValuesR v ~ RecordValuesR v', SameLength v v') => Variant v -> Variant v'
- unsafeUnVariant :: Variant v -> e
- unsafeEmptyVariant :: Variant '[]
- class HasField x (Variant vs) (Maybe v) => MkVariant x v vs | x vs -> v where
- mkVariant1 :: forall k (l :: k) e. Label l -> e -> Variant '[Tagged l e]
- splitVariant1 :: Variant (Tagged s x ': xs) -> Either x (Variant xs)
- splitVariant1' :: Variant (x ': xs) -> Either x (Variant xs)
- extendVariant :: Variant l -> Variant (e ': l)
- 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
- class ShowVariant vs where
- showVariant :: Variant vs -> ShowS
- class ReadVariant vs where
- readVariant :: ReadP (Variant vs)
- class VariantConstrs (xs :: [*]) where
- variantConstrs :: DataType -> proxy xs -> [Constr]
- class GunfoldVariant (es :: [*]) v where
- class GfoldlVariant xs xs' where
- gfoldlVariant :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Variant xs -> c (Variant xs')
- newtype HMapV f = HMapV f
- hMapV :: forall f (x :: [Type]) (y :: [Type]). (HMapAux Variant (HFmap f) x y, SameLength' x y, SameLength' y x) => f -> Variant x -> Variant y
- 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
- type family HMapOutV_gety (x :: [*]) (z :: *) :: [*]
- 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')
- type family UnMaybe le
- class HAllEqVal (x :: [*]) (b :: Bool) | x -> b
- class HAllEqVal' (x :: [*])
- class Unvariant' v e | v -> e where
- unvariant' :: Variant v -> e
- class Unvariant v e | v -> e where
- class Unvariant1 b v e | b v -> e where
- unvariant1 :: Proxy b -> Variant v -> e
- data UnvariantTypeMismatch (vs :: [*])
- unvarianted :: (Unvariant' s a, Unvariant' t b, SameLabels s t, SameLength s t, Functor f) => (a -> f b) -> Variant s -> f (Variant t)
- 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)
- class ZipVariant x y xy | x y -> xy, xy -> x y where
- zipVariant :: Variant x -> Variant y -> Maybe (Variant xy)
- class (SameLength v v', SameLabels v v') => ZipVR fs v v' | fs v -> v' where
- zipVR :: (SameLabels fs v, SameLength fs v, ZipVR fs v v', ZipVRCxt fs v v') => Record fs -> Variant v -> Variant v'
- type family ZipVRCxt (fs :: [*]) (xs :: [*]) (ys :: [*]) :: Constraint
- 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
- data UncurryEq = UncurryEq
- class ProjectVariant x y where
- projectVariant :: Variant x -> Maybe (Variant y)
- class HAllTaggedLV y => ProjectExtendVariant x y where
- projectExtendVariant :: Variant x -> Maybe (Variant y)
- class ProjectExtendVariant' (inY :: Maybe [*]) lv (y :: [*]) where
- projectExtendVariant' :: Proxy inY -> lv -> Maybe (Variant y)
- class (ProjectVariant x yin, ProjectVariant x yout) => SplitVariant x yin yout where
- splitVariant :: Variant x -> Either (Variant yin) (Variant yout)
- class (HAllTaggedLV y, HAllTaggedLV x) => ExtendsVariant x y where
- extendsVariant :: Variant x -> Variant y
- rearrangeVariant :: (SameLength v v', ExtendsVariant v v') => Variant v -> Variant v'
- 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))
- data HCastF = HCastF
- 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))
- class VariantToHMaybied v r | v -> r, r -> v where
- variantToHMaybied :: Variant v -> Record r
- data ConstTaggedNothing = ConstTaggedNothing
- hMaybiedToVariants :: (HFoldr HMaybiedToVariantFs [Variant '[]] r [Variant v], VariantToHMaybied v r) => Record r -> [Variant v]
- data HMaybiedToVariantFs = HMaybiedToVariantFs
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.
p -> ...
case e of p -> ...
do p <- e; ...
- implicit parameters
let ?p = e in ...
- other patterns involved in mutually recursive bindings
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)
Instances
Relabeled Variant Source # | |
Defined in Data.HList.Variant 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 # | |
Defined in Data.HList.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 Source # | Prism (Variant s) (Variant t) (Variant a) (Variant b) |
Defined in Data.HList.Labelable 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 |
Defined in Data.HList.Variant | |
(HPrism x s t a b, to ~ ((->) :: Type -> Type -> Type)) => Labelable (x :: k) Variant s t a b Source # | make a |
Defined in Data.HList.Labelable type LabelableTy Variant :: LabeledOpticType Source # | |
(HasField x (Record vs) a, HFindLabel x vs n, HNat2Integral n) => HasField (x :: k) (Variant vs) (Maybe a) Source # | |
Defined in Data.HList.Variant | |
(ApplyAB f te te', HMapCxt Variant f (l ': ls) (l' ': ls')) => HMapAux Variant f (te ': (l ': ls)) (te' ': (l' ': ls')) Source # | |
ApplyAB f te te' => HMapAux Variant f '[te] '[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 |
(HasField l (Variant r) (Maybe u), HasFieldPath 'True ls u (Maybe v)) => HasFieldPath needJust (Label l ': ls) (Variant r) (Maybe v) Source # | |
Defined in Data.HList.Dredge | |
(Unvariant '[txy] txy, tx ~ Tagged t x, ty ~ Tagged t y, txy ~ Tagged t (x, y)) => HUnzip Variant '[tx] '[ty] '[txy] 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 # | |
(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 # | |
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 ( |
Defined in Data.HList.Variant 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 # |
The last type in the Variant does not need to be Bounded. This
means that
This is a "feature" because it allows an Another difficult choice is that the lower bound is
|
Defined in Data.HList.Variant 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 # | |
Eq (Variant ('[] :: [Type])) Source # | |
(Typeable (Variant v), GfoldlVariant v v, GunfoldVariant v v, VariantConstrs v) => Data (Variant v) Source # | |
Defined in Data.HList.Variant 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 # | |
Defined in Data.HList.Variant 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 # | |
Defined in Data.HList.Variant | |
ReadVariant v => Read (Variant v) Source # | A corresponding read instance |
ShowVariant vs => Show (Variant vs) Source # | Variants are not opaque |
(Semigroup x, Semigroup (Variant (a ': b))) => Semigroup (Variant (Tagged t x ': (a ': b))) Source # | |
Defined in Data.HList.Variant (<>) :: 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 # | |
(Monoid x, Monoid (Variant (a ': b))) => Monoid (Variant (Tagged t x ': (a ': b))) Source # | |
(Unvariant '[Tagged t x] x, Monoid x) => Monoid (Variant '[Tagged t x]) Source # | |
(SameLength s a, ExtendsVariant s a, SameLength b t, ExtendsVariant b t) => Rearranged Variant (s :: [Type]) (t :: [Type]) (a :: [Type]) (b :: [Type]) Source # | |
Defined in Data.HList.Variant rearranged :: (Profunctor p, Functor f) => p (Variant a) (f (Variant b)) -> p (Variant s) (f (Variant t)) Source # | |
type LabelableTy Variant Source # | |
Defined in Data.HList.Labelable | |
type HExtendR le (Variant v) Source # | |
Defined in Data.HList.Variant |
Unsafe operations
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 #
Instances
(HFindLabel x vs n, HNat2Integral n, HasField x (Variant vs) (Maybe v)) => MkVariant (x :: k) v vs Source # | |
Public destructor
hLookupByLabel
(synonym .!.
)
(.!.) :: Variant v -> Label x -> Maybe e hLookupByLabel :: Label x -> Variant v -> Maybe e
extendVariant :: Variant l -> Variant (e ': l) Source #
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".
hPrism :: (Choice p, Applicative f) => Label x -> p a (f b) -> p (Variant s) (f (Variant t)) Source #
Instances
(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 # | |
Defined in Data.HList.Variant |
Read
class ShowVariant vs where Source #
helper class for defining the Show instance
showVariant :: Variant vs -> ShowS Source #
Instances
(ShowLabel l, Show v, lv ~ Tagged l v) => ShowVariant '[lv] Source # | |
Defined in Data.HList.Variant showVariant :: Variant '[lv] -> ShowS Source # | |
(ShowLabel l, Show v, ShowVariant (w ': ws)) => ShowVariant (Tagged l v ': (w ': ws)) Source # | |
Defined in Data.HList.Variant |
Show
class ReadVariant vs where Source #
readVariant :: ReadP (Variant vs) Source #
Instances
ReadVariant ('[] :: [Type]) Source # | |
Defined in Data.HList.Variant readVariant :: ReadP (Variant '[]) Source # | |
(ShowLabel l, Read v, ReadVariant vs, HOccursNot (Label l) (LabelsOf vs)) => ReadVariant (Tagged l v ': vs) Source # | |
Defined in Data.HList.Variant |
Data
class VariantConstrs (xs :: [*]) where Source #
variantConstrs :: DataType -> proxy xs -> [Constr] Source #
Instances
VariantConstrs ('[] :: [Type]) Source # | |
Defined in Data.HList.Variant variantConstrs :: DataType -> proxy '[] -> [Constr] Source # | |
(ShowLabel l, VariantConstrs xs) => VariantConstrs (Tagged l e ': xs) Source # | |
Defined in Data.HList.Variant |
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
Instances
(MkVariant l e v, Data e, GunfoldVariant (b ': bs) v) => GunfoldVariant (Tagged l e ': (b ': bs)) v Source # | |
(MkVariant l e v, Data e) => GunfoldVariant '[Tagged l e] v Source # | |
class GfoldlVariant xs xs' where Source #
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 l v, Data v, MkVariant l v b) => GfoldlVariant '[a] b Source # | |
Defined in Data.HList.Variant | |
(a ~ Tagged l v, MkVariant l v r, Data v, GfoldlVariant (b ': c) r) => GfoldlVariant (a ': (b ': c)) r Source # | |
Defined in Data.HList.Variant |
Map
Apply a function to all possible elements of the variant
HMapV f |
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
type HMapOutV_gety ('[] :: [Type]) z Source # | |
Defined in Data.HList.Variant | |
type HMapOutV_gety (Tagged s x ': xs) z Source # | |
Defined in Data.HList.Variant |
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
Conversion to an untagged value
class HAllEqVal' (x :: [*]) Source #
Instances
HAllEqVal' ('[] :: [Type]) Source # | |
Defined in Data.HList.Variant | |
(HAllEqVal' (ta ': xs), a' ~ a, ta ~ Tagged t a, ta' ~ Tagged t' a') => HAllEqVal' (ta' ': (ta ': xs)) Source # | |
Defined in Data.HList.Variant | |
HAllEqVal' '[x] Source # | |
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))
unvariant' :: Variant v -> e Source #
Instances
(HAllEqVal' (Tagged () e ': v), Unvariant v e) => Unvariant' v e Source # | |
Defined in Data.HList.Variant 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'
class Unvariant1 b v e | b v -> e where Source #
unvariant1 :: Proxy b -> Variant v -> e Source #
Instances
Fail "Unvariant applied to empty variant" => Unvariant1 (b :: k) ('[] :: [Type]) (Proxy "Unvariant applied to empty variant") Source # | |
Defined in Data.HList.Variant | |
v ~ Tagged t1 e => Unvariant1 'True (v ': vs) e Source # | |
Defined in Data.HList.Variant | |
Fail (UnvariantTypeMismatch (v ': vs)) => Unvariant1 'False (v ': vs) (UnvariantTypeMismatch (v ': vs)) Source # | |
Defined in Data.HList.Variant unvariant1 :: Proxy 'False -> Variant (v ': vs) -> UnvariantTypeMismatch (v ': vs) Source # |
data UnvariantTypeMismatch (vs :: [*]) Source #
Instances
Fail (UnvariantTypeMismatch (v ': vs)) => Unvariant1 'False (v ': vs) (UnvariantTypeMismatch (v ': vs)) Source # | |
Defined in Data.HList.Variant 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
Instances
ZipVariant ('[] :: [Type]) ('[] :: [Type]) ('[] :: [Type]) Source # | |
Defined in Data.HList.Variant | |
(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 # | |
Defined in Data.HList.Variant |
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.
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
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
had an FD ZipVR
fs v v'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))
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
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]
is one implementation
of rearrangeVariant
= fromJust
. projectVariant
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
ProjectVariant x ('[] :: [Type]) Source # | |
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 # | |
Defined in Data.HList.Variant |
class HAllTaggedLV y => ProjectExtendVariant x y where Source #
projectExtendVariant = fmapextendVariant
.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
HAllTaggedLV y => ProjectExtendVariant ('[] :: [Type]) y Source # | |
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 # | |
Defined in Data.HList.Variant |
class ProjectExtendVariant' (inY :: Maybe [*]) lv (y :: [*]) where Source #
Instances
ProjectExtendVariant' ('Nothing :: Maybe [Type]) lv y Source # | |
Defined in Data.HList.Variant | |
(MkVariant l v y, lv ~ Tagged l v) => ProjectExtendVariant' ('Just t) lv y Source # | |
Defined in Data.HList.Variant |
class (ProjectVariant x yin, ProjectVariant x yout) => SplitVariant x yin yout where 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 Source # | |
Defined in Data.HList.Variant |
class (HAllTaggedLV y, HAllTaggedLV x) => ExtendsVariant x y where Source #
projectVariant . extendsVariant = Just
(when the types match up)
extendVariant
is a special case
extendsVariant :: Variant x -> Variant y Source #
Instances
(HAllTaggedLV x, Unvariant '[le] e, MkVariant l e x, le ~ Tagged l e) => ExtendsVariant '[le] x Source # | |
Defined in Data.HList.Variant extendsVariant :: Variant '[le] -> Variant x Source # | |
(MkVariant l e y, le ~ Tagged l e, ExtendsVariant (b ': bs) y) => ExtendsVariant (le ': (b ': bs)) y Source # | |
Defined in Data.HList.Variant 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'
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 #
variantToHMaybied :: Variant v -> Record r Source #
Instances
VariantToHMaybied ('[] :: [Type]) ('[] :: [Type]) Source # | |
Defined in Data.HList.Variant 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 # | |
Defined in Data.HList.Variant variantToHMaybied :: Variant (tx ': v) -> Record (tmx ': r) Source # |
data ConstTaggedNothing Source #
Instances
y ~ Tagged t (Maybe e) => ApplyAB ConstTaggedNothing x y Source # | |
Defined in Data.HList.Variant 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 #