A label
Modulerow-types-1.0.1.2Haskell2010
Data.Row.Variants
This module implements extensible variants using closed type families.
- 10 types
- 4 classes
- 38 values
- Packagerow-types-1.0.1.2
- Exports65
- LanguageHaskell2010
- LicenceMIT
- SourceVariants.hs
Types and constraints
8 declarationsThis class gives the string associated with a type-level symbol. There are instances of the class for every concrete literal: "hello", etc.
Are all of the labels in this Row unique?
Equations
AllUniqueLabels ('R r) = AllUniqueLabelsR r
A convenient way to provide common, easy constraints
The variant type.
Instances8AsConstructor', AsConstructor, Eq, Ord, Show, Generic, …
(AllUniqueLabels r, KnownSymbol name, (r .! name) ≈ a, r ≈ ((r .- name) .\/ (name .== a))) => AsConstructor' name (Var r) aDefined in row-types-1.0.1.2 · Data.Row.Variants(AllUniqueLabels r, AllUniqueLabels r', KnownSymbol name, (r .! name) ≈ a, (r' .! name) ≈ b, r' ≈ ((r .- name) .\/ (name .== b))) => AsConstructor name (Var r) (Var r') a bDefined in row-types-1.0.1.2 · Data.Row.VariantsEvery possibility of a row-types based variant has an AsConstructor instance.
Forall r Eq => Eq (Var r)Defined in row-types-1.0.1.2 · Data.Row.Variants(Forall r Eq, Forall r Ord) => Ord (Var r)Defined in row-types-1.0.1.2 · Data.Row.VariantsForall r Show => Show (Var r)Defined in row-types-1.0.1.2 · Data.Row.VariantsGenericVar r => Generic (Var r)Defined in row-types-1.0.1.2 · Data.Row.VariantsForall r NFData => NFData (Var r)Defined in row-types-1.0.1.2 · Data.Row.Variantstype Rep (Var r) = D1 ('MetaDataDefined in row-types-1.0.1.2 · Data.Row.Variants"Var"
"Data.Row.Variants"
"row-types"
'False) (RepVar r)
The kind of rows. This type is only used as a datakind. A row is a typelevel entity telling us which symbols are associated with which types.
Type level version of empty
A lower fixity operator for type equality
Construction
6 declarationsAlias for (r .! l) ≈ a. It is a class rather than an alias, so that
it can be partially applied.
A pattern for variants; can be used to both destruct a variant when in a pattern position or construct one in an expression position.
A quick constructor to create a singleton variant.
A quick destructor for singleton variants.
Initialize a variant from a producer function that accepts labels. If this function returns more than one possibility, then one is chosen arbitrarily to be the value in the variant.
Initialize a variant over a Map.
Extension
Does the row lack (i.e. it does not have) the specified label?
Equations
(.\) ('R '[]) l = Unconstrained(.\) ('R r) l = LacksR l r r
Alias for .\. It is a class rather than an alias, so that it can be partially applied.
Make the variant arbitrarily more diverse.
Modification
If the variant exists at the given label, update it to the given value. Otherwise, do nothing.
If the variant exists at the given label, focus on the value associated with it. Otherwise, do nothing.
Rename the given label.
Destruction
8 declarationsA Variant with no options is uninhabited.
Convert a variant into either the value at the given label or a variant without that label. This is the basic variant destructor.
A version of trial that ignores the leftover variant.
A trial over multiple types
A convenient function for using view patterns when dispatching variants. For example:
myShow :: Var ("y" '::= String :| "x" '::= Int :| Empty) -> String
myShow (view x -> Just n) = "Int of "++show n
myShow (view y -> Just s) = "String of "++sArbitrary variant restriction. Turn a variant into a subset of itself.
Split a variant into two sub-variants.
Types for destruction
A type level way to create a singleton Row.
Native Conversion
7 declarationsThe toNative and fromNative functions allow one to convert between
Vars and regular Haskell data types ("native" types) that have the same
number of constructors such that each constructor has one field and the same
name as one of the options of the Var, which has the same type as that field.
As expected, they compose to form the identity. Alternatively, one may use
fromNativeGeneral, which allows a variant with excess options to still be
transformed to a native type. Because of this, fromNativeGeneral requires a type
application (although fromNative does not). The only requirement is that
the native Haskell data type be an instance of Generic.
For example, consider the following simple data type:
data Pet = Dog {age :: Int} | Cat {age :: Int} deriving (Generic, Show)Then, we have the following:
toNative $ IsJust (Label @"Dog") 3 :: PetDog {age = 3}V.fromNative $ Dog 3 :: Var ("Dog" .== Int .+ "Cat" .== Int){Dog=3}
Convert a variant to a native Haskell type.
Convert a Haskell variant to a row-types Var.
Convert a Haskell variant to a row-types Var.
Row operations
0 declarationsMap
A function to map over a variant given a constraint.
A function to map over a variant given no constraint.
Lifts a natrual transformation over a variant. In other words, it acts as a
variant transformer to convert a variant of f a values to a variant of g a
values. If no constraint is needed, instantiate the first type argument with
Unconstrained1.
A form of transformC that doesn't have a constraint on a
Fold
Any structure over a row in which every element is similarly constrained can be metamorphized into another structure over the same row.
Instances2Forall
Forall ('R '[]) cDefined in row-types-1.0.1.2 · Data.Row.Internal(KnownSymbol ℓ, c τ, Forall ('R ρ) c, FrontExtends ℓ τ ('R ρ), AllUniqueLabels (Extend ℓ τ ('R ρ))) => Forall ('R ((ℓ ':-> τ) ': ρ)) cDefined in row-types-1.0.1.2 · Data.Row.Internal
A standard fold
A fold with labels
A fold over two variants at once. A call eraseZipGeneral f x y will return
f (Left (show l, a, b)) when x and y both have values at the same label l
and will return f (Right ((show l1, a), (show l2, b))) when they have values
at different labels l1 and l2 respectively.
A simpler fold over two variants at once
Applicative-like functions
Traverse a function over a variant.
Traverse a function over a Mapped variant.
Applicative sequencing over a variant
Compose
We can easily convert between mapping two functors over the types of a row and mapping the composition of the two functors. The following two functions perform this composition with the gaurantee that:
compose . uncompose = iduncompose . compose = idConvert from a variant where two functors have been mapped over the types to one where the composition of the two functors is mapped over the types.
Convert from a variant where the composition of two functors have been mapped over the types to one where the two functors are mapped individually one at a time over the types.
labels
Return a list of the labels in a row type.
ApSingle functions
A version of erase that works even when the row-type of the variant argument
is of the form ApSingle fs x.
Performs a functorial-like map over an ApSingle variant.
In other words, it acts as a variant transformer to convert a variant of
f x values to a variant of f y values. If no constraint is needed,
instantiate the first type argument with Unconstrained1.
Like mapSingle, but works over a functor.
A version of eraseZip that works even when the row-types of the variant
arguments are of the form ApSingle fs x.
Coerce
Coerce a variant to a coercible representation. The BiForall in the context
indicates that the type of any option in r1 can be coerced to the type of
the corresponding option in r2.
Internally, this is implemented just with unsafeCoerce, but we provide the following implementation as a proof:
newtype ConstV a b = ConstV { unConstV :: Var a }
newtype ConstV a b = FlipConstV { unFlipConstV :: Var b }
coerceVar :: forall r1 r2. BiForall r1 r2 Coercible => Var r1 -> Var r2
coerceVar = unFlipConstV . biMetamorph @_ @_ @r1 @r2 @Coercible @Either @ConstV @FlipConstV @Const Proxy doNil doUncons doCons . ConstV
where
doNil = impossible . unConstV
doUncons l = bimap ConstV Const . flip trial l . unConstV
doCons :: forall ℓ τ1 τ2 ρ1 ρ2. (KnownSymbol ℓ, Coercible τ1 τ2, AllUniqueLabels (Extend ℓ τ2 ρ2))
=> Label ℓ -> Either (FlipConstV ρ1 ρ2) (Const τ1 τ2)
-> FlipConstV (Extend ℓ τ1 ρ1) (Extend ℓ τ2 ρ2)
doCons l (Left (FlipConstV v)) = FlipConstV $ extend @τ2 l v
doCons l (Right (Const x)) = FlipConstV $ IsJust l (coerce @τ1 @τ2 x)
\\ extendHas @ρ2 @ℓ @τ2