| Copyright | (c) 2024 Eitan Chatav |
|---|---|
| License | MIT |
| Maintainer | eitan.chatav@gmail.com |
| Stability | experimental |
| Portability | non-portable (GHC extensions) |
| Safe Haskell | Safe-Inferred |
| Language | Haskell2010 |
Data.Default.Singletons
Description
This module defines an Optional type with
either a Default promoted value type,
or Some specific demoted value term.
>>>definite (Def :: Opt True)True>>>definite (Some False :: Opt (def :: Bool))False>>>definite (Some True :: Opt False)True>>>maybe "def" show (perhaps (Def :: Opt True))"def">>>maybe "def" show (perhaps (Some True :: Opt True))"True">>>maybe "def" show (perhaps (Some False :: Opt True))"False"
The correspondence between promoted datakinds
and demoted datatypes is inexact.
Usually, Demote t ~ t, but not always such as:
>>>:kind! Demote SymbolDemote Symbol :: * = Text
Because there is no promoted Integer and Rational datakinds in base,
this module defines them as Z and Q.
>>>:kind! Demote ZDemote Z :: * = Integer>>>:kind! Demote QDemote Q :: * = Ratio Integer
The Opt type comes with
Num, Integral, Fractional, and Real instances,
using definite values to do arithmetic,
which let you use literals and arithmetic to construct
Some specific Opt value;
>>>4 :: Opt 20Some 4>>>(Def + 0) * 1 :: Opt (Pos 8 :: Z)Some 8>>>0.5 + Def :: Opt (Neg 1 % 3 :: Q)Some (1 % 6)
and IsString and IsList instances.
>>>"text" :: Opt ("abc" :: Symbol)Some "text">>>"string" :: Opt (['a','b','c'] :: String)Some "string">>>[[1, 2],[3,4]] :: Opt ('[] :: [[Natural]])Some [[1, 2],[3,4]]
Opt is a Monoid which yields
the leftmost specific value when there are Some,
and the Default value when there are none.
>>>definite (mempty :: Opt "xyz")"xyz">>>definite (Def <> "abc" <> "qrs" <> Def :: Opt "xyz")"abc"
You can use Opt as an optional function argument.
>>>:{greet :: Opt "Anon" -> Text greet name = "Welcome, " <> definite name <> "." :}>>>greet "Sarah""Welcome, Sarah.">>>greet Def"Welcome, Anon."
Or, you can use Opt as an optional field in your record type.
>>>:{data Person = Person { name :: Text , age :: Natural , alive :: Opt (True :: Bool) } :}>>>let isAlive person = definite (alive person)>>>let jim = Person {name = "Jim", age = 40, alive = Def}>>>isAlive jimTrue
You almost never need to include the datakind in your
type signatures since it's usually inferrable from def.
Synopsis
- data Opt (def :: k) where
- type SingDef (def :: k) = (SingI def, SingKind k)
- optionally :: forall {k} def. SingDef def => Maybe (Demote k) -> Opt (def :: k)
- definite :: forall {k} def. Opt (def :: k) -> Demote k
- perhaps :: forall {k} def m. Alternative m => Opt (def :: k) -> m (Demote k)
- data Z
- type family Neg n where ...
- data Q = (:%) Z Natural
- type family z % n :: Q where ...
- type family Reduce q :: Q where ...
- type family GCD (a :: Natural) (b :: Natural) :: Natural where ...
- data SInteger (n :: Z) where
- SPos :: SNat n -> SInteger (Pos n)
- SNegOneMinus :: SNat n -> SInteger (NegOneMinus n)
- data SRational (n :: Q) where
- demote :: forall {k} (a :: k). (SingKind k, SingI a) => Demote k
- type family Demote k = (r :: Type) | r -> k
Documentation
Optional Datatype
data Opt (def :: k) where Source #
Constructors
| Def :: forall {k} def. SingDef def => Opt (def :: k) | |
| Some :: forall {k} def. Demote k -> Opt (def :: k) |
Instances
| IsString (Demote k) => IsString (Opt def) Source # | |
Defined in Data.Default.Singletons Methods fromString :: String -> Opt def # | |
| SingDef def => Monoid (Opt def) Source # | |
| Semigroup (Opt def) Source # | |
| IsList (Demote k) => IsList (Opt def) Source # | |
| Num (Demote k) => Num (Opt def) Source # | |
| (SingDef def, Read (Demote k)) => Read (Opt def) Source # | |
| Fractional (Demote k) => Fractional (Opt def) Source # | |
| (SingDef def, Show (Demote k)) => Show (Opt def) Source # | |
| SingDef def => Default (Opt def) Source # | |
Defined in Data.Default.Singletons | |
| (SingDef def, Eq (Demote k)) => Eq (Opt def) Source # | |
| (SingDef def, Ord (Demote k)) => Ord (Opt def) Source # | |
Defined in Data.Default.Singletons | |
| type Item (Opt def) Source # | |
Defined in Data.Default.Singletons | |
perhaps :: forall {k} def m. Alternative m => Opt (def :: k) -> m (Demote k) Source #
Deconstructs an Opt to an Alternative Demoted value.
Def maps to empty,
and Some maps to pure,
inverting optionally.
Promoted Datakinds
Datakind Z, promoting Integer,
>>>:kind! Demote ZDemote Z :: * = Integer
with Pos for constructing nonnegative integer types,
and Neg for constructing nonpositive integer types.
>>>demote @(Pos 90210)90210>>>demote @(Neg 5)-5>>>demote @(Neg 0)0>>>demote @(Pos 0)0
NonNegative integer types are matched cardinally by Pos,
>>>:kind! Pos 9Pos 9 :: Z = Pos 9>>>:kind! Neg 0Neg 0 :: Z = Pos 0
and Negative integer types are matched ordinally by NegOneMinus.
>>>:kind! Neg 6Neg 6 :: Z = NegOneMinus 5>>>:kind! Neg 1Neg 1 :: Z = NegOneMinus 0
Constructors
| Pos Natural | |
| NegOneMinus Natural |
Instances
| Enum Z Source # | |
| Num Z Source # | |
| Read Z Source # | |
| Integral Z Source # | |
| Real Z Source # | |
Defined in Data.Default.Singletons Methods toRational :: Z -> Rational # | |
| Show Z Source # | |
| Eq Z Source # | |
| Ord Z Source # | |
| SingKind Z Source # | |
| KnownNat n => SingI ('NegOneMinus n :: Z) Source # | |
Defined in Data.Default.Singletons Methods sing :: Sing ('NegOneMinus n) # | |
| KnownNat n => SingI ('Pos n :: Z) Source # | |
Defined in Data.Default.Singletons | |
| type Demote Z Source # | |
Defined in Data.Default.Singletons | |
| type Sing Source # | |
Defined in Data.Default.Singletons | |
Datakind Q, promoting Rational,
>>>:kind! Demote QDemote Q :: * = Ratio Integer
with :% for constructing (unreduced) and matching rational types,
>>>demote @(Pos 7 :% 11)7 % 11>>>demote @(Neg 4 :% 6)(-2) % 3>>>:kind Pos 10 :% 10Pos 10 :% 10 :: Q
and % and Reduce for constructing reduced rational types.
>>>:kind! Pos 14 % 49Pos 14 % 49 :: Q = Pos 2 :% 7>>>type Percent n = Pos n :% 100>>>:kind! Percent 10Percent 10 :: Q = Pos 10 :% 100>>>:kind! Reduce (Percent 10)Reduce (Percent 10) :: Q = Pos 1 :% 10
Instances
| Num Q Source # | |
| Read Q Source # | |
| Fractional Q Source # | |
| Real Q Source # | |
Defined in Data.Default.Singletons Methods toRational :: Q -> Rational # | |
| Show Q Source # | |
| Eq Q Source # | |
| Ord Q Source # | |
| SingKind Q Source # | |
| (SingI num, SingI denom) => SingI (num ':% denom :: Q) Source # | |
Defined in Data.Default.Singletons | |
| type Demote Q Source # | |
Defined in Data.Default.Singletons | |
| type Sing Source # | |
Defined in Data.Default.Singletons | |
type family Reduce q :: Q where ... Source #
Perform reduction on a rational type, idempotently.
Reduce (Reduce q) ~ Reduce q
type family GCD (a :: Natural) (b :: Natural) :: Natural where ... Source #
Construct the greatest common divisor of Natural types.
data SInteger (n :: Z) where Source #
Singleton representation for the Z kind.
Constructors
| SPos :: SNat n -> SInteger (Pos n) | |
| SNegOneMinus :: SNat n -> SInteger (NegOneMinus n) |
Reexport Demote
demote :: forall {k} (a :: k). (SingKind k, SingI a) => Demote k #
A convenience function that takes a type as input and demotes it to its
value-level counterpart as output. This uses SingKind and SingI behind
the scenes, so .demote = fromSing sing
This function is intended to be used with TypeApplications. For example:
>>>demote @TrueTrue
>>>demote @(Nothing :: Maybe Ordering)Nothing
>>>demote @(Just EQ)Just EQ
>>>demote @'(True,EQ)(True,EQ)
type family Demote k = (r :: Type) | r -> k #
Get a base type from the promoted kind. For example,
Demote Bool will be the type Bool. Rarely, the type and kind do not
match. For example, Demote Nat is Natural.