| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Data.Variant
Description
Open sum type
V (for Variant) is a sum type, i.e. a wrapper for a value which can be of
different types. For instance in the following code x is a variant whose value
can be an Int, a Float or a String:
import Data.Variant x :: V [Int,Float,String]
We use a type-level list of types to statically constrain the possible value
types. Compared to usual sum types (e.g. Either Int Float) it allows us to
have variants which can contain any number of types and to manipulate
(extend/filter/etc.) the list in a type-safe way and without requiring new data
types.
See also
- Data.Variant.VEither is a variant biased towards the first type in the
list, just like
Either a bis biased towards the second type (b), allowing instances such asinstance Functor (VEither a)which we do not have forV. - Data.Variant.Excepts is a multi-exception monad transformer wrapping
VEither. - Data.Variant.EADT supports recursive sum types based on Variant (Extensible ADTs).
Why Variant?
In the functional programming world we use algebraic data types (ADT), more specifically sum types, to indicate that a value can be of two or more different types:
x,y :: Either String Int x = Left "yo" y = Right 10
What if we want to support more than two types?
Solution 1: sum types
We could use different sum types with different constructors for each arity (number of different types that the value can have).
data SumOf3 a b c = S3_0 a | S3_1 b | S3_2 c data SumOf4 a b c d = S4_0 a | S4_1 b | S4_2 c | S4_3 d
But it is quite hard to work with that many different types and constructors as we cannot easily define generic functions working on different sum types without a combinatorial explosion.
Solution 2: recursive ADT
Instead of adding new sum types we can use a nest of Either:
type SumOf3 a b c = Either a (Either b c) type SumOf4 a b c d = Either a (Either b (Either c d))
Or more generically:
data Union (as :: [Type]) where Union :: Either (Union as) a -> Union (a : as)
This time we can define generic functions without risking a combinatorial
explosion. The drawback however is that we have changed the representation:
instead of tag + value where tag is in the range [0,arity-1] we have a
nest of tag + (tag + (... (tag + value))) where tag is in the range
[0,1]. It is both inefficient in space and in time (accessing the tag value is
in O(arity)).
Solution 3: variant
V gets the best of both approaches: it has the generic interface of
the "recursive ADT" solution and the efficient representation of the "sum types"
solution.
data Variant (types :: [Type]) = Variant {-# UNPACK #-} !Word Any
type role Variant representationalThe efficient representation is ensured by the definition of the V
datatype: an unpacked Word for the tag and a "pointer" to the value.
The phantom type list types contains the list of possible types for the value.
The tag value is used as an index into this list to know the effective type of the
value.
Creating Variant values
The easiest way to create a variant value is to use the V pattern synonym:
x,y :: V [String,Int] x = V "test" y = V @Int 10
Note: for now the compiler cannot use the variant value type list to infer the
type of the variant value! In the previous example we have to specify the Int
type. Even if it is clear (for us) that it is the obvious unique possibility, it
is ambiguous for the compiler.
We can also explicitly create a variant by specifying the index (starting from
0) of the value type with toVariantAt:
x :: V [Int,String,Float] x = toVariantAt @2 5.0
It is especially useful if for some reason we want to have the same type more than once in the variant value type list:
y :: V [Int,Int,String,Int,Float] y = toVariantAt @1 5
Pattern matching
Direct pattern matching with V
Matching a variant value can be done with the V pattern synonym too:
f :: V [String,Int] -> String f = \case V s -> "Found string: " ++ s V (i :: Int) -> "Found int: " ++ show i _ -> undefined
Note: for now the compiler cannot use the variant value type list to infer that the pattern-match is complete. Hence we need the wildcard match to avoid a warning.
See Data.Variant.ContFlow for safe alternatives that do not require a wildcard match and that provide better type inference.
Basic errors
If you try to set or match a value type that is not valid, you get a compile-time error:
x :: V [String,Int] x = V @Float 10 -- error: `Float' is not a member of [String, Int]
Safe pattern matching with continuations
See Data.Variant.ContFlow for safe pattern matching using multi-continuations
(>:> and >%:>) that ensure completeness at compile time.
Operations by index
We can retrieve values by index with fromVariantAt:
x :: V [Int,String,Float] x = toVariantAt @2 5.0 > fromVariantAt @0 x Nothing > fromVariantAt @1 x Nothing > fromVariantAt @2 x Just 5.0
Generic variant functions (variant-polymorphic functions)
Splitting variants
We can chose to handle only a subset of the possible value types of a Variant
by using splitVariant. This is very useful when your variant is open (e.g. an
exception type) and you want to perform an action for some particular types
while ignoring the others (e.g. passing the unhandled exceptions to the caller).
For instance in the following example we only handle Int and Float
values. The other ones are considered as left-overs:
printNum v = case splitVariant @[Float,Int] v of
Right v -> v >%:>
( \f -> putStrLn ("Found float: " ++ show (f :: Float))
, \i -> putStrLn ("Found int: " ++ show (i :: Int))
)
Left leftovers -> putStrLn "Not a supported number!"Note that the printNum function above is generic and can be applied to any
Variant type.
Membership constraints: (:<), (:<<), (:<?) #membership
The c :< cs constraint statically ensures that the type c is in the cs
type list and that we can set and match it in a variant with type V cs. For
example:
newtype Error = Error String showError :: (Error :< cs) => V cs -> String showError = \case V (Error s) -> "Found error: " ++ s _ -> "Not an Error!"
Note that to shorten a list of constraints such as (A :< xs, B :< xs, C :< xs)
you can use the (:<<) operator: [A,B,C] :<< xs.
The c :< cs constraint statically ensures that the type c is in the cs
type list. However in some cases we want to write generic functions that work on
variants even if they cannot contain the given type.
The (:<?) constraint and the VMaybe pattern can be used for this:
showErrorMaybe :: (Error :<? cs) => V cs -> String showErrorMaybe = \case VMaybe (Error s) -> "Found error: " ++ s _ -> "Not an Error!"
Shrinking variants with popVariant
A very common use of variants is to pattern match on a specific value type they
can contain and to get a new variant containing the left-over value types. This
is done with popVariant or popVariantMaybe and the Remove type family.
For example:
filterError :: Error :<? cs => V cs -> V (Remove Error cs)
filterError v = case popVariantMaybe v of
Right (Error s) -> error ("Found error: " ++ s)
Left v' -> v' -- left-over variant!Notice how an Error value cannot be present anymore in the variant type
returned by filterError and how this function is generic as it supports any
variant as an input.
Conversions
Singleton conversion
We can easily convert between a variant with a single value type and this value
type with variantToValue and variantFromValue:
intV :: V [Int] intV = V @Int 10 > variantToValue intV 10 > :t variantFromValue "Test" variantFromValue "Test" :: V [String]
Either conversion
variantFromEither and variantToEither can be used to convert between a
variant of arity 2 and the Either data type:
eith :: Either Int String eith = Left 10 > :t variantFromEither eith variantFromEither eith :: V [String, Int] x,y :: V [String,Int] x = V "test" y = V @Int 10 > variantToEither x Right "test" > variantToEither y Left 10
Extending the list of supported types
We can extend the value types of a variant by appending or prepending a list of
types with appendVariant and prependVariant:
x :: V [String,Int] x = V "test" data A = A data B = B px = prependVariant @[A,B] x ax = appendVariant @[A,B] x > :t ax ax :: V [String, Int, A, B] > :t px px :: V [A, B, String, Int]
Appending and prepending are very cheap operations: appending just messes with types and performs nothing at runtime; prepending only increases the tag value at runtime by a constant number.
Variant lifting (extending and reordering)
We can extend and reorder the value types of a variant with liftVariant:
x :: V [String,Int] x = V "test" -- adding Double and Float, and reordering y :: V [Double,Int,Float,String] y = liftVariant x
You can use the LiftVariant constraint to write generic code and to ensure
that the type list is is a subset of os:
liftX :: (LiftVariant is (Double : Float : is))
=> V is -> V (Double : Float : is)
liftX = liftVariant
> :t liftX x
liftX x :: V [Double, Float, String, Int]Removing duplicates (nub)
If the list of types of a variant contains the same type more than once, we can
decide to only keep one of them with nubVariant:
> z = nubVariant (V "test" :: V [String,Int,Double,Float,Double,String]) > :t z z :: V [String, Int, Double, Float]
Flattening nested variants
If the value types of a variant are themselves variants, you can flatten them
with flattenVariant:
x :: V [String,Int] x = V "test" nest :: V [ V [String,Int], V [Float,Double]] nest = V x > :t flattenVariant nest flattenVariant nest :: V [String, Int, Float, Double]
Joining variants of functors/monads
We can transform a variant of functor values (e.g., V [m a, m b, m c]) into
a single functor value (e.g., m (V [a,b,c])) with joinVariant:
fs0,fs1,fs2 :: V [ Maybe Int, Maybe String, Maybe Double] fs0 = V @(Maybe Int) (Just 10) fs1 = V (Just "Test") fs2 = V @(Maybe Double) Nothing > joinVariant @Maybe fs0 Just (V @Int 10) > joinVariant @Maybe fs1 Just (V @[Char] "Test") > joinVariant @Maybe fs2 Nothing
It also works with IO for example:
ms0,ms1 :: V [ IO Int, IO String, IO Double] ms0 = V @(IO Int) (printRet 10) ms1 = V (printRet "Test") > joinVariant @IO ms0 10 V @Int 10 > :t joinVariant @IO ms0 joinVariant @IO ms0 :: IO (V [Int, String, Double])
Writing generic code requires the use of the JoinVariant constraint and
the resulting list of value types can be obtained with the ExtractM type
family.
With IO it is possible to use joinVariantUnsafe which does not require the
type application and does not use the JoinVariant type-class. However some
other functor types are not supported (e.g., Maybe) and using
joinVariantUnsafe with them makes the program crash at runtime.
Combining two variants (product)
We can combine two variants into a single variant containing a tuple with
productVariant:
fl :: V [Float,Double] fl = V @Float 5.0 d :: V [Int,Word] d = V @Word 10 dfl = productVariant d fl > dfl V @(Word,Float) (10,5.0) > :t dfl dfl :: V [(Int, Float), (Int, Double), (Word, Float), (Word, Double)]
Converting variants to tuples/HList
We can convert a Variant into a tuple of Maybes with variantToTuple:
w :: V [String,Int,Double,Maybe Int] w = V @Double 1.0 > variantToTuple w (Nothing,Nothing,Just 1.0,Nothing)
And similarly into an HList (heterogeneous list) with variantToHList:
> variantToHList w H[Nothing,Nothing,Just 1.0,Nothing]
Mapping
By type
We can easily apply a function f :: A -> B to a variant so that its value
type A is replaced with B. If the value in the variant has type A, then
f is applied to it to get the new value. Example:
x,y :: V [String,Int] x = V "test" y = V @Int 10 > mapVariant ((+5) :: Int -> Int) x V @String "test" > mapVariant ((+5) :: Int -> Int) y V @Int 15
Note that the resulting variant may contain the same type more than once. To
avoid this, we can either use nubVariant or directly use mapNubVariant:
> :t mapVariant (length :: String -> Int) x mapVariant (length :: String -> Int) x :: V [Int, Int] > :t mapNubVariant (length :: String -> Int) x mapNubVariant (length :: String -> Int) x :: V [Int] > mapNubVariant (length :: String -> Int) x V @Int 4
By index
If we know the index of the value type we want to map, we can use
mapVariantAt. Example:
x,y :: V [String,Int] x = V "test" y = V @Int 10 > mapVariantAt @0 length x V @Int 4 > mapVariantAt @0 length y V @Int 10 > mapVariantAt @1 (+5) x V @[Char] "test" > mapVariantAt @1 (+5) y V @Int 15
Note that the compiler uses the type of the element whose index is given as first argument to infer the type of the functions, hence we do not need type ascriptions.
We can use mapVariantAtM to perform an applicative (or monadic) update.
First matching type
A variant can have the same type more than once in its value type list.
mapVariant updates all the matching types in the list but sometimes that is
not what we want. We can use mapVariantAt if we know the index of the type we
want to update. We can also use mapVariantFirst to update only the first
matching type:
vv :: V [Int,Int,Int] vv = toVariantAt @1 5 > r0 = mapVariant (show :: Int -> String) vv > r1 = mapVariantFirst (show :: Int -> String) vv > :t r0 r0 :: V [String,String,String] > :t r1 r1 :: V [String, Int, Int] > r0 V @[Char] "5" > r1 V @Int 5
We can also apply an applicative (or monadic) function with
mapVariantFirstM.
Synopsis
- data V (l :: [Type]) = Variant !Word (Any :: Type)
- variantIndex :: forall (a :: [Type]). V a -> Word
- variantSize :: forall (xs :: [Type]). KnownNat (Length xs) => V xs -> Word
- pattern V :: c :< cs => c -> V cs
- pattern VMaybe :: c :<? cs => c -> V cs
- type (:<) x (xs :: [Type]) = (Member x xs, x :<? xs)
- type family (xs :: [Type]) :<< (ys :: [Type]) where ...
- type (:<?) x (xs :: [Type]) = (PopVariant x xs, ToVariantMaybe x xs)
- toVariantAt :: forall (n :: Nat) (l :: [Type]). KnownNat n => Index n l -> V l
- toVariantHead :: forall x (xs :: [Type]). x -> V (x ': xs)
- toVariantTail :: forall x (xs :: [Type]). V xs -> V (x ': xs)
- fromVariantAt :: forall (n :: Nat) (l :: [Type]). KnownNat n => V l -> Maybe (Index n l)
- fromVariantHead :: forall x (xs :: [Type]). V (x ': xs) -> Maybe x
- popVariantAt :: forall (n :: Nat) (l :: [Type]). KnownNat n => V l -> Either (V (RemoveAt n l)) (Index n l)
- popVariantHead :: forall x (xs :: [Type]). V (x ': xs) -> Either (V xs) x
- mapVariantAt :: forall (n :: Nat) a b (l :: [Type]). (KnownNat n, a ~ Index n l) => (a -> b) -> V l -> V (ReplaceN n b l)
- mapVariantAtM :: forall (n :: Nat) a b (l :: [Type]) m. (KnownNat n, Applicative m, a ~ Index n l) => (a -> m b) -> V l -> m (V (ReplaceN n b l))
- foldMapVariantAt :: forall (n :: Nat) (l :: [Type]) (l2 :: [Type]). (KnownNat n, KnownNat (Length l2)) => (Index n l -> V l2) -> V l -> V (ReplaceAt n l l2)
- foldMapVariantAtM :: forall (n :: Nat) m (l :: [Type]) (l2 :: [Type]). (KnownNat n, KnownNat (Length l2), Monad m) => (Index n l -> m (V l2)) -> V l -> m (V (ReplaceAt n l l2))
- bindVariant :: forall x (xs :: [Type]) (ys :: [Type]). KnownNat (Length ys) => V (x ': xs) -> (x -> V ys) -> V (Concat ys xs)
- constBindVariant :: forall (xs :: [Type]) (ys :: [Type]). V xs -> V ys -> V (Concat ys xs)
- variantHeadTail :: forall x u (xs :: [Type]). (x -> u) -> (V xs -> u) -> V (x ': xs) -> u
- mapVariantHeadTail :: forall x y (xs :: [Type]) (ys :: [Type]). (x -> y) -> (V xs -> V ys) -> V (x ': xs) -> V (y ': ys)
- toVariant :: forall a (l :: [Type]). a :< l => a -> V l
- popVariant :: forall a (xs :: [Type]). a :< xs => V xs -> Either (V (Remove a xs)) a
- popVariantMaybe :: forall a (xs :: [Type]). a :<? xs => V xs -> Either (V (Remove a xs)) a
- fromVariant :: forall a (xs :: [Type]). a :< xs => V xs -> Maybe a
- fromVariantMaybe :: forall a (xs :: [Type]). a :<? xs => V xs -> Maybe a
- fromVariantFirst :: forall a (l :: [Type]). Member a l => V l -> Maybe a
- mapVariantFirst :: forall a b (n :: Nat) (l :: [Type]). (Member a l, n ~ IndexOf a l) => (a -> b) -> V l -> V (ReplaceN n b l)
- mapVariantFirstM :: forall a b (n :: Nat) (l :: [Type]) m. (Member a l, n ~ IndexOf a l, Applicative m) => (a -> m b) -> V l -> m (V (ReplaceN n b l))
- mapVariant :: forall a b (cs :: [Type]). MapVariant a b cs => (a -> b) -> V cs -> V (ReplaceAll a b cs)
- mapNubVariant :: forall a b (cs :: [Type]) (ds :: [Type]) (rs :: [Type]). (MapVariant a b cs, ds ~ ReplaceNS (IndexesOf a cs) b cs, rs ~ Nub ds, LiftVariant ds rs) => (a -> b) -> V cs -> V rs
- foldMapVariantFirst :: forall a (n :: Nat) (l :: [Type]) (l2 :: [Type]). (KnownNat n, KnownNat (Length l2), n ~ IndexOf a l, a ~ Index n l) => (a -> V l2) -> V l -> V (ReplaceAt n l l2)
- foldMapVariantFirstM :: forall a (n :: Nat) (l :: [Type]) (l2 :: [Type]) m. (KnownNat n, KnownNat (Length l2), n ~ IndexOf a l, a ~ Index n l, Monad m) => (a -> m (V l2)) -> V l -> m (V (ReplaceAt n l l2))
- foldMapVariant :: forall a (cs :: [Type]) (ds :: [Type]) (i :: Nat). (i ~ IndexOf a cs, a :< cs) => (a -> V ds) -> V cs -> V (InsertAt i (Remove a cs) ds)
- type family Member (x :: k) (xs :: [k]) where ...
- type family Remove (a :: k) (l :: [k]) :: [k] where ...
- type ReplaceAll a b (cs :: [Type]) = ReplaceNS (IndexesOf a cs) b cs
- type MapVariant a b (cs :: [Type]) = MapVariantIndexes a b cs (IndexesOf a cs)
- alterVariant :: forall c (a :: [Type]). AlterVariant c a => (forall x. c x => x -> x) -> V a -> V a
- traverseVariant :: forall c (a :: [Type]) m. (TraverseVariant c a m, Monad m) => (forall x. c x => x -> m x) -> V a -> m (V a)
- traverseVariant_ :: forall c (a :: [Type]) m. (TraverseVariant c a m, Monad m) => (forall x. c x => x -> m ()) -> V a -> m ()
- reduceVariant :: forall c (a :: [Type]) r. ReduceVariant c a => (forall x. c x => x -> r) -> V a -> r
- class NoConstraint a
- class AlterVariant (c :: Type -> Constraint) (b :: [Type])
- class TraverseVariant (c :: Type -> Constraint) (b :: [Type]) (m :: Type -> Type)
- class ReduceVariant (c :: Type -> Constraint) (b :: [Type])
- appendVariant :: forall (ys :: [Type]) (xs :: [Type]). V xs -> V (Concat xs ys)
- prependVariant :: forall (ys :: [Type]) (xs :: [Type]). KnownNat (Length ys) => V xs -> V (Concat ys xs)
- liftVariant :: forall (ys :: [Type]) (xs :: [Type]). LiftVariant xs ys => V xs -> V ys
- nubVariant :: forall (xs :: [Type]). LiftVariant xs (Nub xs) => V xs -> V (Nub xs)
- productVariant :: forall (xs :: [Type]) (ys :: [Type]). KnownNat (Length ys) => V xs -> V ys -> V (Product xs ys)
- flattenVariant :: forall (xs :: [Type]). Flattenable (V xs) (V (FlattenVariant xs)) => V xs -> V (FlattenVariant xs)
- joinVariant :: JoinVariant m xs => V xs -> m (V (ExtractM m xs))
- joinVariantUnsafe :: forall m (xs :: [Type]) (ys :: [Type]). (Functor m, ys ~ ExtractM m xs) => V xs -> m (V ys)
- splitVariant :: forall (as :: [Type]) (xs :: [Type]). SplitVariant as (Complement xs as) xs => V xs -> Either (V (Complement xs as)) (V as)
- type LiftVariant (xs :: [Type]) (ys :: [Type]) = (LiftVariant' xs ys, xs :<< ys)
- class Flattenable a rs
- type family FlattenVariant (xs :: [Type]) :: [Type] where ...
- type family ExtractM (m :: Type -> Type) (f :: [Type]) :: [Type] where ...
- class JoinVariant (m :: Type -> Type) (xs :: [Type])
- class SplitVariant (as :: [Type]) (rs :: [Type]) (xs :: [Type])
- variantToValue :: V '[a] -> a
- variantFromValue :: a -> V '[a]
- variantToEither :: V '[a, b] -> Either b a
- variantFromEither :: Either a b -> V '[b, a]
- class ContVariant (xs :: [Type]) where
- variantToCont :: V xs -> ContFlow xs r
- variantToContM :: Monad m => m (V xs) -> ContFlow xs (m r)
- contToVariant :: ContFlow xs (V xs) -> V xs
- contToVariantM :: Monad m => ContFlow xs (m (V xs)) -> m (V xs)
- pattern VSilent :: (Member c cs, PopVariant c cs) => c -> V cs
- liftVariant' :: LiftVariant' xs ys => V xs -> V ys
- fromVariant' :: forall a (xs :: [Type]). PopVariant a xs => V xs -> Maybe a
- popVariant' :: PopVariant a xs => V xs -> Either (V (Remove a xs)) a
- toVariant' :: forall a (l :: [Type]). Member a l => a -> V l
- class LiftVariant' (xs :: [Type]) (ys :: [Type])
- class PopVariant a (xs :: [Type])
- class ToVariantMaybe a (xs :: [Type]) where
- toVariantMaybe :: a -> Maybe (V xs)
- showsVariant :: forall (xs :: [Type]). (Typeable xs, ShowTypeList (V xs), ShowVariantValue (V xs)) => Int -> V xs -> ShowS
Documentation
A variant contains a value whose type is at the given position in the type list
Instances
| (Exception x, Typeable xs, Exception (V xs)) => Exception (V (x ': xs)) Source # | |||||
Defined in Data.Variant Methods toException :: V (x ': xs) -> SomeException # fromException :: SomeException -> Maybe (V (x ': xs)) # displayException :: V (x ': xs) -> String # | |||||
| Exception (V ('[] :: [Type])) Source # | |||||
Defined in Data.Variant Methods toException :: V ('[] :: [Type]) -> SomeException # fromException :: SomeException -> Maybe (V ('[] :: [Type])) # displayException :: V ('[] :: [Type]) -> String # | |||||
| (Show x, Show (V xs)) => Show (V (x ': xs)) Source # | Show instance
| ||||
| Show (V ('[] :: [Type])) Source # | |||||
| (NFData x, NFData (V xs)) => NFData (V (x ': xs)) Source # | |||||
Defined in Data.Variant | |||||
| NFData (V ('[] :: [Type])) Source # | |||||
Defined in Data.Variant | |||||
| (Eq (V xs), Eq x) => Eq (V (x ': xs)) Source # | |||||
| Eq (V ('[] :: [Type])) Source # | |||||
| (Ord (V xs), Ord x) => Ord (V (x ': xs)) Source # | |||||
Defined in Data.Variant | |||||
| Ord (V ('[] :: [Type])) Source # | |||||
Defined in Data.Variant Methods compare :: V ('[] :: [Type]) -> V ('[] :: [Type]) -> Ordering # (<) :: V ('[] :: [Type]) -> V ('[] :: [Type]) -> Bool # (<=) :: V ('[] :: [Type]) -> V ('[] :: [Type]) -> Bool # (>) :: V ('[] :: [Type]) -> V ('[] :: [Type]) -> Bool # (>=) :: V ('[] :: [Type]) -> V ('[] :: [Type]) -> Bool # max :: V ('[] :: [Type]) -> V ('[] :: [Type]) -> V ('[] :: [Type]) # min :: V ('[] :: [Type]) -> V ('[] :: [Type]) -> V ('[] :: [Type]) # | |||||
| ContVariant xs => MultiCont (V xs) Source # | |||||
Defined in Data.Variant Associated Types
| |||||
| Flattenable (V ('[] :: [Type])) rs Source # | |||||
Defined in Data.Variant Methods toFlattenVariant :: Word -> V ('[] :: [Type]) -> rs | |||||
| (Flattenable (V ys) (V rs), KnownNat (Length xs)) => Flattenable (V (V xs ': ys)) (V rs) Source # | |||||
Defined in Data.Variant Methods toFlattenVariant :: Word -> V (V xs ': ys) -> V rs | |||||
| type MultiContTypes (V xs) Source # | |||||
Defined in Data.Variant | |||||
variantIndex :: forall (a :: [Type]). V a -> Word Source #
Get Variant index
>>>let x = V "Test" :: V [Int,String,Double]>>>variantIndex x1>>>let y = toVariantAt @0 10 :: V [Int,String,Double]>>>variantIndex y0
variantSize :: forall (xs :: [Type]). KnownNat (Length xs) => V xs -> Word Source #
Get variant size
>>>let x = V "Test" :: V [Int,String,Double]>>>variantSize x3>>>let y = toVariantAt @0 10 :: V [Int,String,Double,Int]>>>variantSize y4
Patterns
pattern V :: c :< cs => c -> V cs Source #
Pattern synonym for Variant
Usage: case v of V (x :: Int) -> ... V (x :: String) -> ...
type (:<) x (xs :: [Type]) = (Member x xs, x :<? xs) Source #
A value of type "x" can be extracted from (V xs)
type (:<?) x (xs :: [Type]) = (PopVariant x xs, ToVariantMaybe x xs) Source #
A value of type "x" **might** be extracted from (V xs). We don't check that "x" is in "xs".
Operations by index
toVariantAt :: forall (n :: Nat) (l :: [Type]). KnownNat n => Index n l -> V l Source #
Set the value with the given indexed type
>>>toVariantAt @1 10 :: V [Word,Int,Double]10
toVariantHead :: forall x (xs :: [Type]). x -> V (x ': xs) Source #
Set the first value
>>>toVariantHead 10 :: V [Int,Float,Word]10
toVariantTail :: forall x (xs :: [Type]). V xs -> V (x ': xs) Source #
Set the tail
>>>let x = V @Int 10 :: V [Int,String,Float]>>>let y = toVariantTail @Double x>>>:t yy :: V [Double, Int, String, Float]
fromVariantAt :: forall (n :: Nat) (l :: [Type]). KnownNat n => V l -> Maybe (Index n l) Source #
Try to get a value by index into the type list
>>>let x = V "Test" :: V [Int,String,Float]>>>fromVariantAt @0 xNothing>>>fromVariantAt @1 xJust "Test">>>fromVariantAt @2 xNothing
fromVariantHead :: forall x (xs :: [Type]). V (x ': xs) -> Maybe x Source #
Try to get the first variant value
>>>let x = V "Test" :: V [Int,String,Float]>>>fromVariantHead xNothing>>>let y = V @Int 10 :: V [Int,String,Float]>>>fromVariantHead yJust 10
popVariantAt :: forall (n :: Nat) (l :: [Type]). KnownNat n => V l -> Either (V (RemoveAt n l)) (Index n l) Source #
Pop a variant value by index, return either the value or the remaining variant
>>>let x = V @Word 10 :: V [Int,Word,Float]>>>popVariantAt @0 xLeft 10>>>popVariantAt @1 xRight 10>>>popVariantAt @2 xLeft 10
popVariantHead :: forall x (xs :: [Type]). V (x ': xs) -> Either (V xs) x Source #
Pop the head of a variant value
>>>let x = V @Word 10 :: V [Int,Word,Float]>>>popVariantHead xLeft 10
>>>let y = V @Int 10 :: V [Int,Word,Float]>>>popVariantHead yRight 10
mapVariantAt :: forall (n :: Nat) a b (l :: [Type]). (KnownNat n, a ~ Index n l) => (a -> b) -> V l -> V (ReplaceN n b l) Source #
Update a single variant value by index
>>>import Data.Char (toUpper)>>>let x = V @String "Test" :: V [Int,String,Float]>>>mapVariantAt @1 (fmap toUpper) x"TEST"
>>>mapVariantAt @0 (+1) x"Test"
mapVariantAtM :: forall (n :: Nat) a b (l :: [Type]) m. (KnownNat n, Applicative m, a ~ Index n l) => (a -> m b) -> V l -> m (V (ReplaceN n b l)) Source #
Applicative update of a single variant value by index
Example with Maybe:
>>>let f s = if s == "Test" then Just (42 :: Word) else Nothing>>>let x = V @String "Test" :: V [Int,String,Float]>>>mapVariantAtM @1 f xJust 42
>>>let y = V @String "NotTest" :: V [Int,String,Float]>>>mapVariantAtM @1 f yNothing
Example with IO:
>>>v <- mapVariantAtM @0 print x
>>>:t vv :: V [(), String, Float]
>>>v <- mapVariantAtM @1 print x"Test"
>>>:t vv :: V [Int, (), Float]
>>>v <- mapVariantAtM @2 print x
>>>:t vv :: V [Int, [Char], ()]
foldMapVariantAt :: forall (n :: Nat) (l :: [Type]) (l2 :: [Type]). (KnownNat n, KnownNat (Length l2)) => (Index n l -> V l2) -> V l -> V (ReplaceAt n l l2) Source #
Update a variant value with a variant and fold the result
>>>newtype Odd = Odd Int deriving (Show)>>>newtype Even = Even Int deriving (Show)>>>let f x = if even x then V (Even x) else V (Odd x) :: V [Odd, Even]>>>foldMapVariantAt @1 f (V @Int 10 :: V [Float,Int,Double])Even 10
>>>foldMapVariantAt @1 f (V @Float 0.5 :: V [Float,Int,Double])0.5
foldMapVariantAtM :: forall (n :: Nat) m (l :: [Type]) (l2 :: [Type]). (KnownNat n, KnownNat (Length l2), Monad m) => (Index n l -> m (V l2)) -> V l -> m (V (ReplaceAt n l l2)) Source #
Update a variant value with a variant and fold the result
bindVariant :: forall x (xs :: [Type]) (ys :: [Type]). KnownNat (Length ys) => V (x ': xs) -> (x -> V ys) -> V (Concat ys xs) Source #
Bind (>>=) for a Variant
constBindVariant :: forall (xs :: [Type]) (ys :: [Type]). V xs -> V ys -> V (Concat ys xs) Source #
Const bind (>>) for a Variant
variantHeadTail :: forall x u (xs :: [Type]). (x -> u) -> (V xs -> u) -> V (x ': xs) -> u Source #
List-like catamorphism
>>>let f = variantHeadTail (\i -> "Found Int: " ++ show i) (const "Something else")>>>f (V @String "Test" :: V [Int,String,Float])"Something else"
>>>f (V @Int 10 :: V [Int,String,Float])"Found Int: 10"
mapVariantHeadTail :: forall x y (xs :: [Type]) (ys :: [Type]). (x -> y) -> (V xs -> V ys) -> V (x ': xs) -> V (y ': ys) Source #
Bimap Variant head and tail
>>>let f = mapVariantHeadTail (+5) (appendVariant @[Double,Char])>>>f (V @Int 10 :: V [Int,Word,Float])15
>>>f (V @Word 20 :: V [Int,Word,Float])20
Operations by type
toVariant :: forall a (l :: [Type]). a :< l => a -> V l Source #
Put a value into a Variant
Use the first matching type index.
popVariant :: forall a (xs :: [Type]). a :< xs => V xs -> Either (V (Remove a xs)) a Source #
Extract a type from a variant. Return either the value of this type or the remaining variant
popVariantMaybe :: forall a (xs :: [Type]). a :<? xs => V xs -> Either (V (Remove a xs)) a Source #
Extract a type from a variant. Return either the value of this type or the remaining variant
fromVariant :: forall a (xs :: [Type]). a :< xs => V xs -> Maybe a Source #
Try to a get a value of a given type from a Variant
Equivalent to pattern V.
>>>let x = toVariantAt @2 10 :: V [Int,String,Int]>>>fromVariant @Int xJust 10
fromVariant @Double x
... error: Double not found in list: [Int, String, Int] ...
fromVariantMaybe :: forall a (xs :: [Type]). a :<? xs => V xs -> Maybe a Source #
Try to a get a value of a given type from a Variant that may not even support the given type.
>>>let x = V @Int 10 :: V [Int,String,Float]>>>fromVariantMaybe @Int xJust 10>>>fromVariantMaybe @Double xNothing
fromVariantFirst :: forall a (l :: [Type]). Member a l => V l -> Maybe a Source #
Pick the first matching type of a Variant
>>>let x = toVariantAt @2 10 :: V [Int,String,Int]>>>fromVariantFirst @Int xNothing
mapVariantFirst :: forall a b (n :: Nat) (l :: [Type]). (Member a l, n ~ IndexOf a l) => (a -> b) -> V l -> V (ReplaceN n b l) Source #
Update the first matching variant value
>>>let x = toVariantAt @0 10 :: V [Int,String,Int]>>>mapVariantFirst @Int (+32) x42
>>>let y = toVariantAt @2 10 :: V [Int,String,Int]>>>mapVariantFirst @Int (+32) y10
mapVariantFirstM :: forall a b (n :: Nat) (l :: [Type]) m. (Member a l, n ~ IndexOf a l, Applicative m) => (a -> m b) -> V l -> m (V (ReplaceN n b l)) Source #
Applicative update of the first matching variant value
Example with Maybe:
>>>let f s = if s == (42 :: Int) then Just "Yeah!" else Nothing>>>mapVariantFirstM f (toVariantAt @0 42 :: V [Int,Float,Int])Just "Yeah!"
>>>mapVariantFirstM f (toVariantAt @2 42 :: V [Int,Float,Int])Just 42
>>>mapVariantFirstM f (toVariantAt @0 10 :: V [Int,Float,Int])Nothing
>>>mapVariantFirstM f (toVariantAt @2 10 :: V [Int,Float,Int])Just 10
Example with IO:
>>>mapVariantFirstM @Int print (toVariantAt @0 42 :: V [Int,Float,Int])42 ()
>>>mapVariantFirstM @Int print (toVariantAt @2 42 :: V [Int,Float,Int])42
mapVariant :: forall a b (cs :: [Type]). MapVariant a b cs => (a -> b) -> V cs -> V (ReplaceAll a b cs) Source #
Map the matching types of a variant
>>>let add1 = mapVariant @Int (+1)>>>add1 (toVariantAt @0 10 :: V [Int,Float,Int,Double])11
>>>add1 (toVariantAt @2 10 :: V [Int,Float,Int, Double])11
mapNubVariant :: forall a b (cs :: [Type]) (ds :: [Type]) (rs :: [Type]). (MapVariant a b cs, ds ~ ReplaceNS (IndexesOf a cs) b cs, rs ~ Nub ds, LiftVariant ds rs) => (a -> b) -> V cs -> V rs Source #
Map the matching types of a variant and nub the result
>>>let add1 = mapNubVariant @Int (+1)>>>add1 (toVariantAt @0 10 :: V [Int,Float,Int,Double])11
>>>add1 (toVariantAt @2 10 :: V [Int,Float,Int, Double])11
foldMapVariantFirst :: forall a (n :: Nat) (l :: [Type]) (l2 :: [Type]). (KnownNat n, KnownNat (Length l2), n ~ IndexOf a l, a ~ Index n l) => (a -> V l2) -> V l -> V (ReplaceAt n l l2) Source #
Update a variant value with a variant and fold the result
foldMapVariantFirstM :: forall a (n :: Nat) (l :: [Type]) (l2 :: [Type]) m. (KnownNat n, KnownNat (Length l2), n ~ IndexOf a l, a ~ Index n l, Monad m) => (a -> m (V l2)) -> V l -> m (V (ReplaceAt n l l2)) Source #
Update a variant value with a variant and fold the result
foldMapVariant :: forall a (cs :: [Type]) (ds :: [Type]) (i :: Nat). (i ~ IndexOf a cs, a :< cs) => (a -> V ds) -> V cs -> V (InsertAt i (Remove a cs) ds) Source #
Update a variant value with a variant and fold the result
>>>newtype Odd = Odd Int deriving (Show)>>>newtype Even = Even Int deriving (Show)>>>let f x = if even x then V (Even x) else V (Odd x) :: V [Odd, Even]>>>foldMapVariant @Int f (V @Int 10 :: V [Float,Int,Double])Even 10
>>>foldMapVariant @Int f (V @Float 0.5 :: V [Float,Int,Double])0.5
type MapVariant a b (cs :: [Type]) = MapVariantIndexes a b cs (IndexesOf a cs) Source #
Generic operations with type classes
alterVariant :: forall c (a :: [Type]). AlterVariant c a => (forall x. c x => x -> x) -> V a -> V a Source #
Alter a variant. You need to specify the constraints required by the modifying function.
Usage:
alterVariant NoConstraint id v
alterVariant Resizable (resize 4) v
- - Multiple constraints: class (Ord a, Num a) => OrdNum a instance (Ord a, Num a) => OrdNum a alterVariant @OrdNum foo v
traverseVariant :: forall c (a :: [Type]) m. (TraverseVariant c a m, Monad m) => (forall x. c x => x -> m x) -> V a -> m (V a) Source #
Traverse a variant. You need to specify the constraints required by the modifying function.
traverseVariant_ :: forall c (a :: [Type]) m. (TraverseVariant c a m, Monad m) => (forall x. c x => x -> m ()) -> V a -> m () Source #
Traverse a variant. You need to specify the constraints required by the modifying function.
reduceVariant :: forall c (a :: [Type]) r. ReduceVariant c a => (forall x. c x => x -> r) -> V a -> r Source #
Reduce a variant to a single value by using a class function. You need to specify the constraints required by the modifying function.
>>>let v = V "Yes" :: V [String,Bool,Char]>>>reduceVariant @Show show v"\"Yes\""
>>>let n = V (10 :: Int) :: V [Int,Word,Integer]>>>reduceVariant @Integral fromIntegral n :: Int10
class NoConstraint a Source #
Useful to specify a "Type -> Constraint" function returning an empty constraint
Instances
| NoConstraint a Source # | |
Defined in Data.Variant | |
class AlterVariant (c :: Type -> Constraint) (b :: [Type]) Source #
Minimal complete definition
alterVariant'
Instances
| AlterVariant c ('[] :: [Type]) Source # | |
Defined in Data.Variant | |
| (AlterVariant c xs, c x) => AlterVariant c (x ': xs) Source # | |
Defined in Data.Variant | |
class TraverseVariant (c :: Type -> Constraint) (b :: [Type]) (m :: Type -> Type) Source #
Minimal complete definition
traverseVariant'
Instances
| TraverseVariant c ('[] :: [Type]) m Source # | |
Defined in Data.Variant | |
| (TraverseVariant c xs m, c x, Monad m) => TraverseVariant c (x ': xs) m Source # | |
Defined in Data.Variant | |
class ReduceVariant (c :: Type -> Constraint) (b :: [Type]) Source #
Minimal complete definition
reduceVariant'
Instances
| ReduceVariant c ('[] :: [Type]) Source # | |
Defined in Data.Variant Methods reduceVariant' :: (forall a. c a => a -> r) -> Word -> (Any :: Type) -> r | |
| (ReduceVariant c xs, c x) => ReduceVariant c (x ': xs) Source # | |
Defined in Data.Variant Methods reduceVariant' :: (forall a. c a => a -> r) -> Word -> (Any :: Type) -> r | |
Conversions between variants
appendVariant :: forall (ys :: [Type]) (xs :: [Type]). V xs -> V (Concat xs ys) Source #
Extend a variant by appending other possible values
prependVariant :: forall (ys :: [Type]) (xs :: [Type]). KnownNat (Length ys) => V xs -> V (Concat ys xs) Source #
Extend a variant by prepending other possible values
liftVariant :: forall (ys :: [Type]) (xs :: [Type]). LiftVariant xs ys => V xs -> V ys Source #
Lift a variant into another
Set values to the first matching type
nubVariant :: forall (xs :: [Type]). LiftVariant xs (Nub xs) => V xs -> V (Nub xs) Source #
Nub the type list
productVariant :: forall (xs :: [Type]) (ys :: [Type]). KnownNat (Length ys) => V xs -> V ys -> V (Product xs ys) Source #
Product of two variants
flattenVariant :: forall (xs :: [Type]). Flattenable (V xs) (V (FlattenVariant xs)) => V xs -> V (FlattenVariant xs) Source #
Flatten variants in a variant
joinVariant :: JoinVariant m xs => V xs -> m (V (ExtractM m xs)) Source #
Join on a variant
Transform a variant of applicatives as follow: f :: V [m a, m b, m c] -> m (V [a,b,c]) f = joinVariant @m
joinVariantUnsafe :: forall m (xs :: [Type]) (ys :: [Type]). (Functor m, ys ~ ExtractM m xs) => V xs -> m (V ys) Source #
Join on a variant in an unsafe way.
Works with IO for example but not with Maybe.
splitVariant :: forall (as :: [Type]) (xs :: [Type]). SplitVariant as (Complement xs as) xs => V xs -> Either (V (Complement xs as)) (V as) Source #
Split a variant in two
type LiftVariant (xs :: [Type]) (ys :: [Type]) = (LiftVariant' xs ys, xs :<< ys) Source #
xs is liftable in ys
class Flattenable a rs Source #
Minimal complete definition
toFlattenVariant
Instances
| Flattenable (V ('[] :: [Type])) rs Source # | |
Defined in Data.Variant Methods toFlattenVariant :: Word -> V ('[] :: [Type]) -> rs | |
| (Flattenable (V ys) (V rs), KnownNat (Length xs)) => Flattenable (V (V xs ': ys)) (V rs) Source # | |
Defined in Data.Variant Methods toFlattenVariant :: Word -> V (V xs ': ys) -> V rs | |
type family FlattenVariant (xs :: [Type]) :: [Type] where ... Source #
Equations
| FlattenVariant ('[] :: [Type]) = '[] :: [Type] | |
| FlattenVariant (V xs ': ys) = Concat xs (FlattenVariant ys) | |
| FlattenVariant (y ': ys) = y ': FlattenVariant ys |
class JoinVariant (m :: Type -> Type) (xs :: [Type]) Source #
Minimal complete definition
Instances
| JoinVariant m ('[] :: [Type]) Source # | |
Defined in Data.Variant | |
| (Functor m, ExtractM m (m a ': xs) ~ (a ': ExtractM m xs), JoinVariant m xs) => JoinVariant m (m a ': xs) Source # | |
Defined in Data.Variant | |
class SplitVariant (as :: [Type]) (rs :: [Type]) (xs :: [Type]) Source #
Minimal complete definition
splitVariant'
Instances
| SplitVariant as rs ('[] :: [Type]) Source # | |
Defined in Data.Variant | |
| (n ~ MaybeIndexOf x as, m ~ MaybeIndexOf x rs, SplitVariant as rs xs, KnownNat m, KnownNat n) => SplitVariant as rs (x ': xs) Source # | |
Defined in Data.Variant Methods splitVariant' :: V (x ': xs) -> Either (V rs) (V as) | |
Conversions to/from other data types
variantToValue :: V '[a] -> a Source #
Retrieve a single value
variantFromValue :: a -> V '[a] Source #
Create a variant from a single value
variantToEither :: V '[a, b] -> Either b a Source #
Convert a variant of two values in a Either
variantFromEither :: Either a b -> V '[b, a] Source #
Lift an Either into a Variant (reversed order by convention)
Continuations
class ContVariant (xs :: [Type]) where Source #
Methods
variantToCont :: V xs -> ContFlow xs r Source #
Convert a variant into a multi-continuation
variantToContM :: Monad m => m (V xs) -> ContFlow xs (m r) Source #
Convert a variant into a multi-continuation
contToVariant :: ContFlow xs (V xs) -> V xs Source #
Convert a multi-continuation into a Variant
contToVariantM :: Monad m => ContFlow xs (m (V xs)) -> m (V xs) Source #
Convert a multi-continuation into a Variant
Instances
| ContVariant '[a, b, c, d, e, f, g, h, i, j, k, l] Source # | |
Defined in Data.Variant Methods variantToCont :: V '[a, b, c, d, e, f, g, h, i, j, k, l] -> ContFlow '[a, b, c, d, e, f, g, h, i, j, k, l] r Source # variantToContM :: Monad m => m (V '[a, b, c, d, e, f, g, h, i, j, k, l]) -> ContFlow '[a, b, c, d, e, f, g, h, i, j, k, l] (m r) Source # contToVariant :: ContFlow '[a, b, c, d, e, f, g, h, i, j, k, l] (V '[a, b, c, d, e, f, g, h, i, j, k, l]) -> V '[a, b, c, d, e, f, g, h, i, j, k, l] Source # contToVariantM :: Monad m => ContFlow '[a, b, c, d, e, f, g, h, i, j, k, l] (m (V '[a, b, c, d, e, f, g, h, i, j, k, l])) -> m (V '[a, b, c, d, e, f, g, h, i, j, k, l]) Source # | |
| ContVariant '[a, b, c, d, e, f, g, h, i, j, k] Source # | |
Defined in Data.Variant Methods variantToCont :: V '[a, b, c, d, e, f, g, h, i, j, k] -> ContFlow '[a, b, c, d, e, f, g, h, i, j, k] r Source # variantToContM :: Monad m => m (V '[a, b, c, d, e, f, g, h, i, j, k]) -> ContFlow '[a, b, c, d, e, f, g, h, i, j, k] (m r) Source # contToVariant :: ContFlow '[a, b, c, d, e, f, g, h, i, j, k] (V '[a, b, c, d, e, f, g, h, i, j, k]) -> V '[a, b, c, d, e, f, g, h, i, j, k] Source # contToVariantM :: Monad m => ContFlow '[a, b, c, d, e, f, g, h, i, j, k] (m (V '[a, b, c, d, e, f, g, h, i, j, k])) -> m (V '[a, b, c, d, e, f, g, h, i, j, k]) Source # | |
| ContVariant '[a, b, c, d, e, f, g, h, i, j] Source # | |
Defined in Data.Variant Methods variantToCont :: V '[a, b, c, d, e, f, g, h, i, j] -> ContFlow '[a, b, c, d, e, f, g, h, i, j] r Source # variantToContM :: Monad m => m (V '[a, b, c, d, e, f, g, h, i, j]) -> ContFlow '[a, b, c, d, e, f, g, h, i, j] (m r) Source # contToVariant :: ContFlow '[a, b, c, d, e, f, g, h, i, j] (V '[a, b, c, d, e, f, g, h, i, j]) -> V '[a, b, c, d, e, f, g, h, i, j] Source # contToVariantM :: Monad m => ContFlow '[a, b, c, d, e, f, g, h, i, j] (m (V '[a, b, c, d, e, f, g, h, i, j])) -> m (V '[a, b, c, d, e, f, g, h, i, j]) Source # | |
| ContVariant '[a, b, c, d, e, f, g, h, i] Source # | |
Defined in Data.Variant Methods variantToCont :: V '[a, b, c, d, e, f, g, h, i] -> ContFlow '[a, b, c, d, e, f, g, h, i] r Source # variantToContM :: Monad m => m (V '[a, b, c, d, e, f, g, h, i]) -> ContFlow '[a, b, c, d, e, f, g, h, i] (m r) Source # contToVariant :: ContFlow '[a, b, c, d, e, f, g, h, i] (V '[a, b, c, d, e, f, g, h, i]) -> V '[a, b, c, d, e, f, g, h, i] Source # contToVariantM :: Monad m => ContFlow '[a, b, c, d, e, f, g, h, i] (m (V '[a, b, c, d, e, f, g, h, i])) -> m (V '[a, b, c, d, e, f, g, h, i]) Source # | |
| ContVariant '[a, b, c, d, e, f, g, h] Source # | |
Defined in Data.Variant Methods variantToCont :: V '[a, b, c, d, e, f, g, h] -> ContFlow '[a, b, c, d, e, f, g, h] r Source # variantToContM :: Monad m => m (V '[a, b, c, d, e, f, g, h]) -> ContFlow '[a, b, c, d, e, f, g, h] (m r) Source # contToVariant :: ContFlow '[a, b, c, d, e, f, g, h] (V '[a, b, c, d, e, f, g, h]) -> V '[a, b, c, d, e, f, g, h] Source # contToVariantM :: Monad m => ContFlow '[a, b, c, d, e, f, g, h] (m (V '[a, b, c, d, e, f, g, h])) -> m (V '[a, b, c, d, e, f, g, h]) Source # | |
| ContVariant '[a, b, c, d, e, f, g] Source # | |
Defined in Data.Variant Methods variantToCont :: V '[a, b, c, d, e, f, g] -> ContFlow '[a, b, c, d, e, f, g] r Source # variantToContM :: Monad m => m (V '[a, b, c, d, e, f, g]) -> ContFlow '[a, b, c, d, e, f, g] (m r) Source # contToVariant :: ContFlow '[a, b, c, d, e, f, g] (V '[a, b, c, d, e, f, g]) -> V '[a, b, c, d, e, f, g] Source # contToVariantM :: Monad m => ContFlow '[a, b, c, d, e, f, g] (m (V '[a, b, c, d, e, f, g])) -> m (V '[a, b, c, d, e, f, g]) Source # | |
| ContVariant '[a, b, c, d, e, f] Source # | |
Defined in Data.Variant Methods variantToCont :: V '[a, b, c, d, e, f] -> ContFlow '[a, b, c, d, e, f] r Source # variantToContM :: Monad m => m (V '[a, b, c, d, e, f]) -> ContFlow '[a, b, c, d, e, f] (m r) Source # contToVariant :: ContFlow '[a, b, c, d, e, f] (V '[a, b, c, d, e, f]) -> V '[a, b, c, d, e, f] Source # contToVariantM :: Monad m => ContFlow '[a, b, c, d, e, f] (m (V '[a, b, c, d, e, f])) -> m (V '[a, b, c, d, e, f]) Source # | |
| ContVariant '[a, b, c, d, e] Source # | |
Defined in Data.Variant Methods variantToCont :: V '[a, b, c, d, e] -> ContFlow '[a, b, c, d, e] r Source # variantToContM :: Monad m => m (V '[a, b, c, d, e]) -> ContFlow '[a, b, c, d, e] (m r) Source # contToVariant :: ContFlow '[a, b, c, d, e] (V '[a, b, c, d, e]) -> V '[a, b, c, d, e] Source # contToVariantM :: Monad m => ContFlow '[a, b, c, d, e] (m (V '[a, b, c, d, e])) -> m (V '[a, b, c, d, e]) Source # | |
| ContVariant '[a, b, c, d] Source # | |
Defined in Data.Variant Methods variantToCont :: V '[a, b, c, d] -> ContFlow '[a, b, c, d] r Source # variantToContM :: Monad m => m (V '[a, b, c, d]) -> ContFlow '[a, b, c, d] (m r) Source # contToVariant :: ContFlow '[a, b, c, d] (V '[a, b, c, d]) -> V '[a, b, c, d] Source # contToVariantM :: Monad m => ContFlow '[a, b, c, d] (m (V '[a, b, c, d])) -> m (V '[a, b, c, d]) Source # | |
| ContVariant '[a, b, c] Source # | |
Defined in Data.Variant Methods variantToCont :: V '[a, b, c] -> ContFlow '[a, b, c] r Source # variantToContM :: Monad m => m (V '[a, b, c]) -> ContFlow '[a, b, c] (m r) Source # contToVariant :: ContFlow '[a, b, c] (V '[a, b, c]) -> V '[a, b, c] Source # contToVariantM :: Monad m => ContFlow '[a, b, c] (m (V '[a, b, c])) -> m (V '[a, b, c]) Source # | |
| ContVariant '[a, b] Source # | |
Defined in Data.Variant | |
| ContVariant '[a] Source # | |
Defined in Data.Variant | |
Internals
pattern VSilent :: (Member c cs, PopVariant c cs) => c -> V cs Source #
Silent pattern synonym for Variant
Usage: case v of VSilent (x :: Int) -> ... VSilent (x :: String) -> ...
liftVariant' :: LiftVariant' xs ys => V xs -> V ys Source #
fromVariant' :: forall a (xs :: [Type]). PopVariant a xs => V xs -> Maybe a Source #
Try to a get a value of a given type from a Variant (silent)
popVariant' :: PopVariant a xs => V xs -> Either (V (Remove a xs)) a Source #
Remove a type from a variant
toVariant' :: forall a (l :: [Type]). Member a l => a -> V l Source #
Put a value into a Variant (silent)
Use the first matching type index.
class LiftVariant' (xs :: [Type]) (ys :: [Type]) Source #
xs is liftable in ys
Minimal complete definition
Instances
| LiftVariant' ('[] :: [Type]) ys Source # | |
Defined in Data.Variant | |
| (LiftVariant' xs ys, KnownNat (IndexOf x ys)) => LiftVariant' (x ': xs) ys Source # | |
Defined in Data.Variant Methods liftVariant' :: V (x ': xs) -> V ys Source # | |
class PopVariant a (xs :: [Type]) Source #
Minimal complete definition
Instances
| PopVariant a ('[] :: [Type]) Source # | |
Defined in Data.Variant | |
| (PopVariant a xs', n ~ MaybeIndexOf a xs, xs' ~ RemoveAt1 n xs, Remove a xs' ~ Remove a xs, KnownNat n, xs ~ (y ': ys)) => PopVariant a (y ': ys) Source # | |
Defined in Data.Variant | |
class ToVariantMaybe a (xs :: [Type]) where Source #
Put a value into a variant if possible
>>>toVariantMaybe "Test" :: Maybe (V [Int,Float])Nothing
>>>toVariantMaybe "Test" :: Maybe (V [Int,Float,String])Just "Test"
Methods
toVariantMaybe :: a -> Maybe (V xs) Source #
Put a value into a Variant, when the Variant's row contains that type.
Instances
| ToVariantMaybe a ('[] :: [Type]) Source # | |
Defined in Data.Variant | |
| (n ~ MaybeIndexOf a xs, KnownNat n, xs ~ (y ': ys)) => ToVariantMaybe a (y ': ys) Source # | |
Defined in Data.Variant Methods toVariantMaybe :: a -> Maybe (V (y ': ys)) Source # | |