packages feed

typelits-witnesses 0.3.0.3 → 0.4.0.0

raw patch · 6 files changed

+447/−1041 lines, 6 filesdep +dependent-sumdep −constraintsdep −reflectiondep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: dependent-sum

Dependencies removed: constraints, reflection

Dependency ranges changed: base

API changes (from Hackage documentation)

- GHC.TypeLits.List: [:<#] :: (KnownNat n, KnownNats ns) => !(Proxy n) -> !(NatList ns) -> NatList (n : ns)
- GHC.TypeLits.List: [:<$] :: (KnownSymbol s, KnownSymbols ss) => !(Proxy s) -> !(SymbolList ss) -> SymbolList (s : ss)
- GHC.TypeLits.List: [SomeNats] :: KnownNats ns => !(NatList ns) -> SomeNats
- GHC.TypeLits.List: [SomeSymbols] :: KnownSymbols ss => !(SymbolList ss) -> SomeSymbols
- GHC.TypeLits.List: [ØNL] :: NatList '[]
- GHC.TypeLits.List: [ØSL] :: SymbolList '[]
- GHC.TypeLits.List: class KnownNats (ns :: [Nat])
- GHC.TypeLits.List: class KnownSymbols (ss :: [Symbol])
- GHC.TypeLits.List: data NatList :: [Nat] -> Type
- GHC.TypeLits.List: data SomeNats :: Type
- GHC.TypeLits.List: data SomeSymbols :: Type
- GHC.TypeLits.List: data SymbolList :: [Symbol] -> Type
- GHC.TypeLits.List: elimNatList :: forall p ns. () => p '[] -> (forall m ms. (KnownNat m, KnownNats ms) => Proxy m -> p ms -> p (m : ms)) -> NatList ns -> p ns
- GHC.TypeLits.List: elimSymbolList :: forall p ss. () => p '[] -> (forall t ts. (KnownSymbol t, KnownSymbols ts) => Proxy t -> p ts -> p (t : ts)) -> SymbolList ss -> p ss
- GHC.TypeLits.List: instance (GHC.TypeLits.KnownSymbol s, GHC.TypeLits.List.KnownSymbols ss) => GHC.TypeLits.List.KnownSymbols (s : ss)
- GHC.TypeLits.List: instance (GHC.TypeNats.KnownNat n, GHC.TypeLits.List.KnownNats ns) => GHC.TypeLits.List.KnownNats (n : ns)
- GHC.TypeLits.List: instance GHC.Show.Show (GHC.TypeLits.List.NatList ns)
- GHC.TypeLits.List: instance GHC.Show.Show (GHC.TypeLits.List.SymbolList ns)
- GHC.TypeLits.List: instance GHC.TypeLits.List.KnownNats '[]
- GHC.TypeLits.List: instance GHC.TypeLits.List.KnownSymbols '[]
- GHC.TypeLits.List: mapNatList :: (forall n. KnownNat n => Proxy n -> SomeNat) -> NatList ns -> SomeNats
- GHC.TypeLits.List: mapNatList' :: (SomeNat -> SomeNat) -> SomeNats -> SomeNats
- GHC.TypeLits.List: mapSymbolList :: (forall s. KnownSymbol s => Proxy s -> SomeSymbol) -> SymbolList ss -> SomeSymbols
- GHC.TypeLits.List: mapSymbolList' :: (SomeSymbol -> SomeSymbol) -> SomeSymbols -> SomeSymbols
- GHC.TypeLits.List: natsList :: KnownNats ns => NatList ns
- GHC.TypeLits.List: natsVal :: KnownNats ns => p ns -> [Integer]
- GHC.TypeLits.List: reifyNats :: [Integer] -> (forall ns. KnownNats ns => NatList ns -> r) -> r
- GHC.TypeLits.List: reifyNats' :: [Integer] -> r -> (forall ns. KnownNats ns => NatList ns -> r) -> r
- GHC.TypeLits.List: reifySymbols :: [String] -> (forall ss. KnownSymbols ss => SymbolList ss -> r) -> r
- GHC.TypeLits.List: sameNats :: NatList ns -> NatList ms -> Maybe (ns :~: ms)
- GHC.TypeLits.List: sameSymbols :: SymbolList ns -> SymbolList ms -> Maybe (ns :~: ms)
- GHC.TypeLits.List: someNatsVal :: [Integer] -> Maybe SomeNats
- GHC.TypeLits.List: someNatsValPos :: [Integer] -> SomeNats
- GHC.TypeLits.List: someSymbolsVal :: [String] -> SomeSymbols
- GHC.TypeLits.List: symbolsList :: KnownSymbols ss => SymbolList ss
- GHC.TypeLits.List: symbolsVal :: KnownSymbols ss => p ss -> [String]
- GHC.TypeLits.List: traverseNatList :: forall f ns. Applicative f => (forall n. KnownNat n => Proxy n -> f SomeNat) -> NatList ns -> f SomeNats
- GHC.TypeLits.List: traverseNatList' :: forall f. Applicative f => (SomeNat -> f SomeNat) -> SomeNats -> f SomeNats
- GHC.TypeLits.List: traverseNatList_ :: forall f a ns. Applicative f => (forall n. KnownNat n => Proxy n -> f a) -> NatList ns -> f ()
- GHC.TypeLits.List: traverseSymbolList :: forall f ss. Applicative f => (forall s. KnownSymbol s => Proxy s -> f SomeSymbol) -> SymbolList ss -> f SomeSymbols
- GHC.TypeLits.List: traverseSymbolList' :: forall f. Applicative f => (SomeSymbol -> f SomeSymbol) -> SomeSymbols -> f SomeSymbols
- GHC.TypeLits.List: traverseSymbolList_ :: forall f ss. Applicative f => (forall s a. KnownSymbol s => Proxy s -> f a) -> SymbolList ss -> f ()
- GHC.TypeLits.Witnesses: dictNatVal :: forall n. Dict (KnownNat n) -> Integer
- GHC.TypeLits.Witnesses: entailAdd :: forall n m. (KnownNat n, KnownNat m) :- KnownNat (n + m)
- GHC.TypeLits.Witnesses: entailExp :: forall n m. (KnownNat n, KnownNat m) :- KnownNat (n ^ m)
- GHC.TypeLits.Witnesses: entailMul :: forall n m. (KnownNat n, KnownNat m) :- KnownNat (n * m)
- GHC.TypeLits.Witnesses: entailSub :: forall n m. (KnownNat n, KnownNat m) :- KnownNat (n - m)
- GHC.TypeLits.Witnesses: infixl 6 %-
- GHC.TypeLits.Witnesses: infixl 7 %*
- GHC.TypeLits.Witnesses: infixr 8 %^
- GHC.TypeLits.Witnesses: natDict :: KnownNat n => p n -> Dict (KnownNat n)
- GHC.TypeLits.Witnesses: withNatOp :: (KnownNat n, KnownNat m) => (Dict (KnownNat n) -> Dict (KnownNat m) -> Dict (KnownNat q)) -> p n -> p m -> (KnownNat q => r) -> r
+ GHC.TypeLits.Compare: cmpNatGOrdering :: SCmpNat n m -> GOrdering n m
+ GHC.TypeLits.Witnesses: (%<=?) :: SNat n -> SNat m -> n :<=? m
+ GHC.TypeLits.Witnesses: SNat :: SNat n
+ GHC.TypeLits.Witnesses: SSymbol :: SSymbol n
+ GHC.TypeLits.Witnesses: data Natural
+ GHC.TypeLits.Witnesses: data SNat n
+ GHC.TypeLits.Witnesses: data SSymbol n
+ GHC.TypeLits.Witnesses: data SomeNat
+ GHC.TypeLits.Witnesses: data SomeSymbol
+ GHC.TypeLits.Witnesses: fromSNat :: SNat n -> Natural
+ GHC.TypeLits.Witnesses: fromSSymbol :: SSymbol n -> String
+ GHC.TypeLits.Witnesses: instance Data.GADT.Compare.GCompare GHC.TypeLits.Witnesses.SNat
+ GHC.TypeLits.Witnesses: instance Data.GADT.Compare.GCompare GHC.TypeLits.Witnesses.SSymbol
+ GHC.TypeLits.Witnesses: instance Data.GADT.Compare.GEq GHC.TypeLits.Witnesses.SNat
+ GHC.TypeLits.Witnesses: instance Data.GADT.Compare.GEq GHC.TypeLits.Witnesses.SSymbol
+ GHC.TypeLits.Witnesses: instance Data.GADT.Show.GShow GHC.TypeLits.Witnesses.SNat
+ GHC.TypeLits.Witnesses: instance Data.GADT.Show.GShow GHC.TypeLits.Witnesses.SSymbol
+ GHC.TypeLits.Witnesses: instance Data.Type.Equality.TestEquality GHC.TypeLits.Witnesses.SNat
+ GHC.TypeLits.Witnesses: instance Data.Type.Equality.TestEquality GHC.TypeLits.Witnesses.SSymbol
+ GHC.TypeLits.Witnesses: instance GHC.Classes.Eq (GHC.TypeLits.Witnesses.SNat n)
+ GHC.TypeLits.Witnesses: instance GHC.Classes.Eq (GHC.TypeLits.Witnesses.SSymbol n)
+ GHC.TypeLits.Witnesses: instance GHC.Classes.Ord (GHC.TypeLits.Witnesses.SNat n)
+ GHC.TypeLits.Witnesses: instance GHC.Classes.Ord (GHC.TypeLits.Witnesses.SSymbol n)
+ GHC.TypeLits.Witnesses: instance GHC.Show.Show (GHC.TypeLits.Witnesses.SNat n)
+ GHC.TypeLits.Witnesses: instance GHC.Show.Show (GHC.TypeLits.Witnesses.SSymbol n)
+ GHC.TypeLits.Witnesses: minusSNat :: SNat n -> SNat m -> Either (CmpNat n m :~: 'LT) (SNat (n - m))
+ GHC.TypeLits.Witnesses: minusSNat_ :: SNat n -> SNat m -> Maybe (SNat (n - m))
+ GHC.TypeLits.Witnesses: pattern FromSNat :: SNat n -> Natural
+ GHC.TypeLits.Witnesses: pattern FromSSymbol :: SSymbol n -> String
+ GHC.TypeLits.Witnesses: pattern SomeNat_ :: SNat n -> SomeNat
+ GHC.TypeLits.Witnesses: pattern SomeSymbol_ :: SSymbol n -> SomeSymbol
+ GHC.TypeLits.Witnesses: sCmpNat :: SNat n -> SNat m -> SCmpNat n m
+ GHC.TypeLits.Witnesses: toSomeNat :: Natural -> SomeNat
+ GHC.TypeLits.Witnesses: toSomeSymbol :: String -> SomeSymbol
+ GHC.TypeLits.Witnesses: unsafeLiftNatOp1 :: (Natural -> Natural) -> SNat n -> SNat m
+ GHC.TypeLits.Witnesses: unsafeLiftNatOp2 :: (Natural -> Natural -> Natural) -> SNat n -> SNat m -> SNat o
+ GHC.TypeLits.Witnesses: withKnownNat :: SNat n -> (KnownNat n => r) -> r
+ GHC.TypeLits.Witnesses: withKnownSymbol :: SSymbol n -> (KnownSymbol n => r) -> r
+ GHC.TypeLits.Witnesses: withSomeNat :: Natural -> (forall n. SNat n -> r) -> r
+ GHC.TypeLits.Witnesses: withSomeSymbol :: String -> (forall n. SSymbol n -> r) -> r
- GHC.TypeLits.Compare: (%<=?) :: (KnownNat m, KnownNat n) => p m -> q n -> (m :<=? n)
+ GHC.TypeLits.Compare: (%<=?) :: (KnownNat m, KnownNat n) => p m -> q n -> m :<=? n
- GHC.TypeLits.Compare: [LE] :: ((m <=? n) :~: 'True) -> (m :<=? n)
+ GHC.TypeLits.Compare: [LE] :: ((m <=? n) :~: 'True) -> m :<=? n
- GHC.TypeLits.Compare: [NLE] :: ((m <=? n) :~: 'False) -> ((n <=? m) :~: 'True) -> (m :<=? n)
+ GHC.TypeLits.Compare: [NLE] :: ((m <=? n) :~: 'False) -> ((n <=? m) :~: 'True) -> m :<=? n
- GHC.TypeLits.Compare: cmpNatEq :: (CmpNat m n :~: 'EQ) -> (m :~: n)
+ GHC.TypeLits.Compare: cmpNatEq :: (CmpNat m n :~: 'EQ) -> m :~: n
- GHC.TypeLits.Compare: cmpNatLE :: SCmpNat m n -> (m :<=? n)
+ GHC.TypeLits.Compare: cmpNatLE :: SCmpNat m n -> m :<=? n
- GHC.TypeLits.Compare: eqCmpNat :: (m :~: n) -> (CmpNat m n :~: 'EQ)
+ GHC.TypeLits.Compare: eqCmpNat :: (m :~: n) -> CmpNat m n :~: 'EQ
- GHC.TypeLits.Witnesses: (%*) :: forall n m. Dict (KnownNat n) -> Dict (KnownNat m) -> Dict (KnownNat (n * m))
+ GHC.TypeLits.Witnesses: (%*) :: SNat n -> SNat m -> SNat (n - m)
- GHC.TypeLits.Witnesses: (%+) :: forall n m. Dict (KnownNat n) -> Dict (KnownNat m) -> Dict (KnownNat (n + m))
+ GHC.TypeLits.Witnesses: (%+) :: SNat n -> SNat m -> SNat (n + m)
- GHC.TypeLits.Witnesses: (%-) :: forall n m. Dict (KnownNat n) -> Dict (KnownNat m) -> Dict (KnownNat (n - m))
+ GHC.TypeLits.Witnesses: (%-) :: SNat n -> SNat m -> SNat (n - m)
- GHC.TypeLits.Witnesses: (%^) :: forall n m. Dict (KnownNat n) -> Dict (KnownNat m) -> Dict (KnownNat (n ^ m))
+ GHC.TypeLits.Witnesses: (%^) :: SNat n -> SNat m -> SNat (n ^ m)

Files

CHANGELOG.md view
@@ -1,5 +1,25 @@+Changelog+=========++Version 0.4.0.0+---------------++<https://github.com/mstksg/typelits-witnesses/releases/tag/v0.4.0.0>++*June 20, 2019*++*   Complete overhaul of *GHC.TypeLits.Witnesses* to more or less match the+    interface of singletons.  This changes the role of the module to be a+    "lightweight" version of the singletons library as it pertains to `Nat` and+    `Symbol`.+*   Removal of the *GHC.TypeLits.List* module.  We could perform the same+    overhaul as *GHC.TypeLits.Witnesses*, but it is complex enough that it+    would be better to just use *singletons* instead at that point.+*   Remove all external dependencies, except for *base* and *dependent-sum*.+*   Break compatibility with GHC < 8.2+ Version 0.3.0.3-===============+---------------  <https://github.com/mstksg/typelits-witnesses/releases/tag/v0.3.0.3> @@ -9,7 +29,7 @@ *   Break compatibility with GHC < 8.0  Version 0.3.0.2-===============+---------------  <https://github.com/mstksg/typelits-witnesses/releases/tag/v0.3.0.2> @@ -19,7 +39,7 @@     take different "proxy" types (`p` and `q`).  Version 0.3.0.1-===============+---------------  <https://github.com/mstksg/typelits-witnesses/releases/tag/v0.3.0.1> @@ -27,7 +47,7 @@     haddocks for *GHC.TypeLits.List*.  Version 0.3.0.0-===============+---------------  <https://github.com/mstksg/typelits-witnesses/releases/tag/v0.3.0.0> @@ -40,7 +60,7 @@     because it's just so much more unweidly than using *singletons*.  Version 0.2.3.0-===============+---------------  <https://github.com/mstksg/typelits-witnesses/releases/tag/v0.2.3.0> @@ -48,7 +68,7 @@     inequalities on `KnownNat`s and associated utility functions.  Version 0.2.2.0-===============+---------------  <https://github.com/mstksg/typelits-witnesses/releases/tag/v0.2.2.0> @@ -56,7 +76,7 @@     and `sameSymbols`.  Version 0.2.1.0-===============+---------------  <https://github.com/mstksg/typelits-witnesses/releases/tag/v0.2.1.0> @@ -64,7 +84,7 @@     `NatList` and `SymbolList`.  Version 0.2.0.0-===============+---------------  <https://github.com/mstksg/typelits-witnesses/releases/tag/v0.2.0.0> @@ -77,7 +97,7 @@     the *reflection* package is very strong and worth preserving, I think.  Version 0.1.2.0-===============+---------------  <https://github.com/mstksg/typelits-witnesses/releases/tag/v0.1.2.0> @@ -91,7 +111,7 @@     are both the same.  Version 0.1.1.0-===============+---------------  <https://github.com/mstksg/typelits-witnesses/releases/tag/v0.1.1.0> @@ -99,7 +119,7 @@     `SomeSymbols`.  It really doesn't make any sense for them to be lazy.  Version 0.1.0.1-===============+---------------  <https://github.com/mstksg/typelits-witnesses/releases/tag/v0.1.0.1> @@ -107,7 +127,7 @@     Hackage.  Version 0.1.0.0-===============+---------------  <https://github.com/mstksg/typelits-witnesses/releases/tag/v0.1.0.0> 
README.md view
@@ -6,266 +6,17 @@ [![typelits-witnesses on Stackage Nightly](http://stackage.org/package/typelits-witnesses/badge/nightly)](http://stackage.org/nightly/package/typelits-witnesses) [![Build Status](https://travis-ci.org/mstksg/typelits-witnesses.svg?branch=master)](https://travis-ci.org/mstksg/typelits-witnesses) --Provides witnesses for `KnownNat` and `KnownSymbol` instances for various-operations on GHC TypeLits --- in particular, the arithmetic operations-defined in `GHC.TypeLits`, and also for type-level lists of `KnownNat` and-`KnownSymbol` instances.--This is useful for situations where you have `KnownNat n`, and you want to-prove to GHC `KnownNat (n + 3)`, or `KnownNat (2*n + 4)`.--It's also useful for when you want to work with type level lists of-`KnownNat`/`KnownSymbol` instances and singletons for traversing them, and be-able to apply analogies of `natVal`/`symbolVal` to lists with analogies for-`SomeNat` and `SomeSymbol`.+This library contains: -Note that most of the functionality in this library can be reproduced in a more-generic way using the great [singletons][] library.  The versions here are-provided as a "plumbing included" alternative that makes some commonly found-design patterns involving GHC's TypeLits functionality a little smoother,-especially when working with external libraries or GHC TypeLit's `Nat`-comparison API.+*   A small specialized subset of the *[singletons][]* library as it pertains to+    `Nat` and `Symbol`, for when you need some simple functionality without+    wanting to invoke the entire *singletons* library.+*   Operations for manipulating these singletons and `KnownNat` and+    `KnownSymbol` instances, such as addition and multiplication of+    singletons/`KnownNat` instances.+*   Operations for the comparison of `Nat`s in a way that works well with+    *GHC.TypeLits*'s different comparison systems.  This is helpful for+    bridging together libraries that use different systems; this functionality+    is not yet provided by *singletons*.  [singletons]: https://hackage.haskell.org/package/singletons--GHC.TypeLits.Compare-----------------------Provides tools for refining upper and lower bounds on `KnownNat`s and proving-inequalities involving *GHC.TypeLits*'s comparison API. (Both with `<=?` and-`CmpNat`).--If a library function requires `1 <= n` constraint, but only `KnownNat n` is-available:--~~~haskell-foo :: (KnownNat n, 1 <= n) => Proxy n -> Int--bar :: KnownNat n => Proxy n -> Int-bar n = case Proxy @1 %<=? n of-          LE  Refl -> foo n-          NLE _    -> 0-~~~--`foo` requires that `1 <= n`, but `bar` has to handle all cases of `n`.  `%<=?`-lets you compare the `KnownNat`s in two `Proxy`s and returns a `:<=?`, which-has two constructors, `LE` and `NLE`.--If you pattern match on the result, in the `LE` branch, the constraint-`1 <= n` will be satisfied according to GHC, so `bar` can safely call-`foo`, and GHC will recognize that `1 <= n`.--In the `NLE` branch, the constraint that `1 > n` is satisfied, so any-functions that require that constraint would be callable.--For convenience, `isLE` and `isNLE` are also offered:--~~~haskell-bar :: KnownNat n => Proxy n -> Int-bar n = case Proxy @1 `isLE` n of-          Just Refl -> foo n-          Nothing   -> 0-~~~--Similarly, if a library function requires something involving `CmpNat`,-you can use `cmpNat` and the `SCmpNat` type:--~~~haskell-foo1 :: (KnownNat n, CmpNat 5 n ~ LT) => Proxy n -> Int-foo2 :: (KnownNat n, CmpNat 5 n ~ GT) => Proxy n -> Int--bar :: KnownNat n => Proxy n -> Int-bar n = case Proxy @5 `cmpNat` n of-          CLT Refl -> foo1 n-          CEQ _    -> 0-          CGT Refl -> foo2 n-~~~--You can use the `Refl` that `cmpNat` gives you with `flipCmpNat` and-`cmpNatLE` to "flip" the inequality or turn it into something compatible-with `<=?` (useful for when you have to work with libraries that mix the-two methods) or `cmpNatEq` and `eqCmpNat` to get to/from witnesses for-equality of the two `Nat`s.---GHC.TypeLits.Witnesses-------------------------**SOFT DEPRECATED**: Use *[singletons][]* library instead!  However, this-module is still here in case people want the functionality of *singletons*-without requiring the entire library.--Provides witnesses for instances arising from the arithmetic operations-defined in `GHC.TypeLits`.--In general, if you have `KnownNat n`, GHC can't infer `KnownNat (n + 1)`;-and if you have `KnownNat m`, as well, GHC can't infer `KnownNat (n + m)`.--This can be extremely annoying when dealing with libraries and applications-where one regularly adds and subtracts type-level nats and expects `KnownNat`-instances to follow.  For example, vector concatenation of length-encoded-vector types can be:--~~~haskell-concat :: (KnownNat n, KnownNat m)-       => Vector n       a-       -> Vector m       a-       -> Vector (n + m) a-~~~--But, `n + m` now does not have a `KnownNat` instance, which severely hinders-what you can do with this!--Consider this concrete (but silly) example:--~~~haskell-getDoubled :: KnownNat n => Proxy n -> Integer-getDoubled p = natVal (Proxy @(n * 2))-~~~--Which is supposed to call `natVal` with `n * 2`.  However, this fails, because-while `n` is a `KnownNat`, `n * 2` is not necessarily so.  This module lets-you re-assure GHC that this is okay.--The most straightforward/high-level usage is with `withNatOp`:--~~~haskell-getDoubled :: forall n. KnownNat n => Proxy n -> Integer-getDoubled p = withNatOp (%*) p (Proxy @2) $-    natVal (Proxy @(n * 2))-~~~--Within the scope of the argument of-`withNatOp (%*) (Proxy @n) (Proxy @m)`, `n * m` is an instance-of `KnownNat`, so you can use `natVal` on it, and get the expected result:--~~~haskell-> getDoubled (Proxy @12)-24-~~~--There are four "nat operations" defined here, corresponding to the four-type-level operations on `Nat` provided in `GHC.TypeLits`: `(%+)`, `(%-)`,-`(%*)`, and `(%^)`, corresponding to addition, subtraction, multiplication, and-exponentiation, respectively.--Note that `(%-)` is implemented in a way that allows for the result to be a-*negative* `Nat`.--There are more advanced operations dealing with low-level machinery, as well,-in the module.  See module documentation for more detail.--### Singletons replacement--This module is deprecated, and it is recommended you use the functionality from-the *[singletons][]* package instead.  A direct translation using `Proxy` would-be:--~~~haskell-getDoubled :: forall n. KnownNat n => Proxy n -> Integer-getDoubled p = withKnownNat (SNat @n %:* SNat @2) $-    natVal (Proxy @(n * 2))-~~~--But one using singletons throughout the whole process would be:--~~~haskell-getDoubled :: forall n. KnownNat n => Sing n -> Integer-getDoubled s = withKnownNat (s %:* SNat @2) $-    natVal (Proxy @(n * 2))-~~~---GHC.TypeLits.List----------------------**HARD DEPRECATED: Use *[singletons][]* library instead!  This module is-extremely unweildy, and using *singletons* is much, much smoother on many-levels, and integrates everything together in a nice way.  This module will-likely be removed in a future version.--Provides analogies of `KnownNat`, `SomeNat`, `natVal`, etc., to type-level-lists of `KnownNat` instances, and also singletons for iterating over-type-level lists of `Nat`s and `Symbol`s.--If you had `KnownNats ns`, then you have two things you can do with it; first,-`natsVal`, which is like `natVal` but for type-level lists of `KnownNats`:--~~~haskell-> natsVal (Proxy @[1,2,3])-[1,2,3]-~~~--And more importantly, `natsList`, which provides singletons that you can-pattern match on to "reify" the structure of the list, getting a `Proxy n` for-every item in the list with a `KnownNat`/`KnownSymbol` instance in scope for-you to use:--~~~haskell-printNats :: NatList ns -> IO ()-printNats nl = case nl of-                 ØNL       ->-                   return ()-                 p :># nl' -> do-                   print $ natVal p-                   printNats nl'-~~~--~~~haskell-> printNats (natsList :: @[1,2,3])-1-2-3-~~~--Without this, there is no way to "iterate over" and "access" every `Nat` in a-list of `KnownNat`s.  You can't "iterate" over `[1,2,3]` in `Proxy [1,2,3]`,-but you can iterate over them in `NatList [1,2,3]`.--This module also lets you "reify" lists of `Integer`s or `String`s into-`NatList`s and `SymbolList`s, so you can access them at the type level for-some dependent types fun.--~~~haskell-> reifyNats [1,2,3] $ \nl -> do-    print nl-    printNats nl-Proxy :<# Proxy :<# Proxy :<# ØNL-1-2-3-~~~--Another thing you can do is provide witneses that two `[Nat]`s or `[Symbol]`s-are the same/were instantiated with the same numbers/symbols.--~~~haskell-> reifyNats [1,2,3] $ \ns -> do-  reifyNats [1,2,3] $ \ms -> do-    case sameNats ns ms of-      Just Refl -> -- in this branch, ns and ms are the same.-      Nothing   -> -- in this branch, they aren't-~~~--The above would match on the `Just Refl` branch.--See module documentation for more details and variations.--### Singletons replacement--This module is deprecated, and it is recommended you use the functionality from-the *[singletons][]* package instead.  `natsVal` is `fromSing`, `reifyNats` is-`toSing`/`withSomeSing`, `sameNats` is simply `%~`, and you can traverse/reify-singletons of lists too:--~~~haskell-printNats :: forall (ns :: [Nat]). Sing ns -> IO ()-printNats ss = case ss of-                 SNil             ->-                   return ()-                 s `SCons` ss' -> do-                   print $ fromSing s-                   printNats ss'-~~~-
src/GHC/TypeLits/Compare.hs view
@@ -9,8 +9,6 @@  -- | -- Module      : GHC.TypeLits.Compare--- Description : Tools and singletons for proving and refining inequalities---               and bounds on GHC TypeLits types using '<=' and '<=?' -- Copyright   : (c) Justin Le 2016 -- License     : MIT -- Maintainer  : justin@jle.im@@ -26,7 +24,7 @@ -- @'KnownNat' n@ is available: -- -- @--- foo :: (KnownNat n, 1 '<=' n) => 'Proxy' n -> Int+-- foo :: (KnownNat n, 1 '<=' n) => 'Data.Proxy.Proxy' n -> Int -- -- bar :: KnownNat n => Proxy n -> Int -- bar n = case (Proxy :: Proxy 1) '%<=?' n of@@ -35,7 +33,7 @@ -- @ -- -- @foo@ requires that @1 <= n@, but @bar@ has to handle all cases of @n@.--- @%<=?@ lets you compare the 'KnownNat's in two 'Proxy's and returns+-- @%<=?@ lets you compare the 'KnownNat's in two 'Data.Proxy.Proxy's and returns -- a @:<=?@, which has two constructors, 'LE' and 'NLE'. -- -- If you pattern match on the result, in the 'LE' branch, the constraint@@ -73,7 +71,9 @@ -- with '<=?' (useful for when you have to work with libraries that mix the -- two methods) or 'cmpNatEq' and 'eqCmpNat' to get to/from witnesses for -- equality of the two 'Nat's.-+--+-- This module is useful for helping bridge between libraries that use+-- different 'Nat'-based comparison systems in their type constraints. module GHC.TypeLits.Compare   ( -- * '<=' and '<=?'     (:<=?)(..)@@ -89,8 +89,8 @@   , cmpNatEq   , eqCmpNat   , reflCmpNat-    -- ** Interfacing with '<=?'   , cmpNatLE+  , cmpNatGOrdering   )   where @@ -98,7 +98,11 @@ import           Data.Type.Equality import           GHC.TypeLits import           Unsafe.Coerce+import           Data.GADT.Compare +-- | Simplified version of '%<=?': check if @m@ is less than or equal to to+-- @n@.  If it is, match on @'Just' 'Refl'@ to get GHC to believe it,+-- within the body of the pattern match. isLE     :: (KnownNat m, KnownNat n)     => p m@@ -108,6 +112,9 @@              LE  Refl -> Just Refl              NLE _ _  -> Nothing +-- | Simplified version of '%<=?': check if @m@ is not less than or equal+-- to to @n@.  If it is, match on @'Just' 'Refl'@ to get GHC to believe it,+-- within the body of the pattern match. isNLE     :: (KnownNat m, KnownNat n)     => p m@@ -117,10 +124,13 @@     NLE Refl Refl -> Just Refl     LE  _         -> Nothing +-- | Two possible ordered relationships between two natural numbers. data (:<=?) :: Nat -> Nat -> Type where     LE  :: ((m <=? n) :~: 'True)  -> (m :<=? n)     NLE :: ((m <=? n) :~: 'False) -> ((n <=? m) :~: 'True) -> (m :<=? n) +-- | Compare @m@ and @n@, classifying their relationship into some+-- constructor of ':<=?'. (%<=?)      :: (KnownNat m, KnownNat n)      => p m@@ -129,11 +139,14 @@ m %<=? n | natVal m <= natVal n = LE  (unsafeCoerce Refl)          | otherwise            = NLE (unsafeCoerce Refl) (unsafeCoerce Refl) +-- | Three possible ordered relationships between two natural numbers. data SCmpNat :: Nat -> Nat -> Type where     CLT :: (CmpNat m n :~: 'LT) -> SCmpNat m n     CEQ :: (CmpNat m n :~: 'EQ) -> (m :~: n) -> SCmpNat m n     CGT :: (CmpNat m n :~: 'GT) -> SCmpNat m n +-- | Compare @m@ and @n@, classifying their relationship into some+-- constructor of 'SCmpNat'. cmpNat     :: (KnownNat m, KnownNat n)     => p m@@ -144,21 +157,36 @@                EQ -> CEQ (unsafeCoerce Refl) (unsafeCoerce Refl)                GT -> CGT (unsafeCoerce Refl) +-- | Flip an inequality. flipCmpNat :: SCmpNat m n -> SCmpNat n m flipCmpNat = \case CLT Refl      -> CGT (unsafeCoerce Refl)                    CEQ Refl Refl -> CEQ (unsafeCoerce Refl) Refl                    CGT Refl      -> CLT (unsafeCoerce Refl) +-- | @'CmpNat' m n@ being 'EQ' implies that @m@ is equal to @n@. cmpNatEq :: (CmpNat m n :~: 'EQ) -> (m :~: n) cmpNatEq = \case Refl -> unsafeCoerce Refl +-- | A witness of equality implies that @'CmpNat' m n@ is 'Eq'. eqCmpNat :: (m :~: n) -> (CmpNat m n :~: 'EQ) eqCmpNat = \case Refl -> unsafeCoerce Refl +-- | Inject a witness of equality into an 'SCmpNat' at 'CEQ'. reflCmpNat :: (m :~: n) -> SCmpNat m n reflCmpNat r = CEQ (eqCmpNat r) r +-- | Convert to ':<=?' cmpNatLE :: SCmpNat m n -> (m :<=? n) cmpNatLE = \case CLT Refl      -> LE  (unsafeCoerce Refl)                  CEQ Refl Refl -> LE  (unsafeCoerce Refl)                  CGT Refl      -> NLE (unsafeCoerce Refl) (unsafeCoerce Refl)++-- | Convert to 'GOrdering'+--+-- @since 0.4.0.0+cmpNatGOrdering :: SCmpNat n m -> GOrdering n m+cmpNatGOrdering = \case+    CLT Refl      -> GLT+    CEQ Refl Refl -> GEQ+    CGT Refl      -> GGT+
− src/GHC/TypeLits/List.hs
@@ -1,503 +0,0 @@-{-# LANGUAGE ConstraintKinds      #-}-{-# LANGUAGE FlexibleContexts     #-}-{-# LANGUAGE GADTs                #-}-{-# LANGUAGE KindSignatures       #-}-{-# LANGUAGE LambdaCase           #-}-{-# LANGUAGE PolyKinds            #-}-{-# LANGUAGE RankNTypes           #-}-{-# LANGUAGE ScopedTypeVariables  #-}-{-# LANGUAGE StandaloneDeriving   #-}-{-# LANGUAGE TypeFamilies         #-}-{-# LANGUAGE TypeInType           #-}-{-# LANGUAGE TypeOperators        #-}-{-# LANGUAGE UndecidableInstances #-}---- |--- Module      : GHC.TypeLits.List--- Description : Typeclasses, singletons, and reifiers for type-level lists---               of 'Nat's and 'Symbol's.--- Copyright   : (c) Justin Le 2016--- License     : MIT--- Maintainer  : justin@jle.im--- Stability   : unstable--- Portability : non-portable--------- Provides the 'KnownNats' and 'KnownSymbols' typeclasses in analogy to--- 'KnownNat' and 'KnownSymbol' from "GHC.TypeLits".  Also provides--- singleton-esque structures for traversing over type-level lists of--- 'Nat's and 'Symbol's.  Comes with continuation-style reifiers and--- existential types for dependent typing usage, and as an analogy with--- 'SomeNat' and 'SomeSymbol'.------ See typeclass documentations and README for more information.--module GHC.TypeLits.List-  {-# DEPRECATED "Use singletons package instead" #-} (-  -- * 'KnownNats'-    KnownNats(..)-  , SomeNats(..)-  , NatList(..)-  , someNatsVal-  , someNatsValPos-  , reifyNats-  , reifyNats'-  , sameNats-  , elimNatList-  -- ** Traversals-  , traverseNatList-  , traverseNatList'-  , traverseNatList_-  -- *** Maps-  , mapNatList-  , mapNatList'-  -- * 'KnownSymbols'-  , KnownSymbols(..)-  , SomeSymbols(..)-  , SymbolList(..)-  , someSymbolsVal-  , reifySymbols-  , sameSymbols-  , elimSymbolList-  -- ** Traversals-  , traverseSymbolList-  , traverseSymbolList'-  , traverseSymbolList_-  -- *** Maps-  , mapSymbolList-  , mapSymbolList'-  ) where--import           Data.Functor.Identity-import           Data.Kind-import           Data.Proxy-import           Data.Reflection-import           Data.Type.Equality-import           GHC.TypeLits----- | @'KnownNats' ns@ is intended to represent that every 'Nat' in the--- type-level list 'ns' is itself a 'KnownNat' (meaning, you can use--- 'natVal' to get its corresponding 'Integer').------ In practice, just knowing that every item has a 'KnownNat' instance is--- not enough; it's nice, but unless you're able to "iterate" over every--- 'Nat' in the list, it's of limited use.  That's why this class also--- provides a constructor for @'NatList' ns@, so that you can produce--- a 'NatList' for every @'KnownNat' ns@, which you can iterate over to get--- @'Proxy' n@s for every 'n' in 'ns' along with the @'KnownNat' n@--- instances.------ It also has an analogy to 'natVal', 'natsVal', which lets you get a list--- of the represented 'Integer's for, say, @'Proxy' [1,2,3]@.------ __Deprecated:__ Use 'SingI' from /singletons/ instead.-class KnownNats (ns :: [Nat]) where-    -- | __Deprecated:__ Use 'fromSing' from /singletons/ instead.-    natsVal  :: p ns -> [Integer]-    -- | __Deprecated:__ Use 'sing' from /singletons/ instead.-    natsList :: NatList ns-{-# DEPRECATED KnownNats "Use SingI from the singletons package instead" #-}-{-# DEPRECATED natsVal "Use fromSing from the singletons package instead" #-}-{-# DEPRECATED natsList "Use sing from the singletons package instead" #-}--instance KnownNats '[] where-    natsVal  _ = []-    natsList   = ØNL--instance (KnownNat n, KnownNats ns) => KnownNats (n ': ns) where-    natsVal  _ = natVal (Proxy :: Proxy n) : natsVal (Proxy :: Proxy ns)-    natsList   = Proxy :<# natsList---- | Represents unknown type-level lists of type-level natural numbers.--- It's a 'NatList', but you don't know what the list contains at--- compile-time.------ __Deprecated:__ Use 'SomeSing' from /singletons/ instead.-data SomeNats :: Type where-    SomeNats :: KnownNats ns => !(NatList ns) -> SomeNats-{-# DEPRECATED SomeNats "Use SomeSing from the singletons package instead" #-}---- | Singleton-esque type for "traversing" over type-level lists of 'Nat's.--- Essentially contains a (value-level) list of @'Proxy' n@s, but each 'n'--- has a 'KnownNat' instance for you to use.  At runtime (after type--- erasure), is more or less equivalent to a @['Integer']@.------ Typically generated using 'natsList'.------ __Deprecated:__ Use 'Sing' from /singletons/ instead.-data NatList :: [Nat] -> Type where-    ØNL   :: NatList '[]-    (:<#) :: (KnownNat n, KnownNats ns)-          => !(Proxy n) -> !(NatList ns) -> NatList (n ': ns)-{-# DEPRECATED NatList "Use Sing from the singletons package instead" #-}--infixr 5 :<#-deriving instance Show (NatList ns)---- | Utility function for traversing over all of the @'Proxy' n@s in--- a 'NatList', each with the corresponding 'KnownNat' instance available.--- Gives the the ability to "change" the represented natural number to--- a new one, in a 'SomeNat'.------ Can be considered a form of a @Traversal' 'SomeNats' 'SomeNat'@.-traverseNatList-    :: forall f ns. Applicative f-    => (forall n. KnownNat n => Proxy n -> f SomeNat)-    -> NatList ns-    -> f SomeNats-traverseNatList f = go-  where-    go :: forall ms. NatList ms -> f SomeNats-    go = \case-      ØNL      -> pure $ SomeNats ØNL-      n :<# ns -> merge <$> f n <*> go ns-    merge :: SomeNat -> SomeNats -> SomeNats-    merge = \case-      SomeNat n -> \case-        SomeNats ns ->-          SomeNats (n :<# ns)---- | Like 'traverseNatList', but literally actually a @Traversal'--- 'SomeNats' 'SomeNat'@, avoiding the Rank-2 types, so is usable with--- lens-library machinery.-traverseNatList'-    :: forall f. Applicative f-    => (SomeNat -> f SomeNat)-    -> SomeNats-    -> f SomeNats-traverseNatList' f = \case-    SomeNats ns -> traverseNatList (f . SomeNat) ns---- | Utility function for traversing over all of the @'Proxy' n@s in--- a 'NatList', each with the corresponding 'KnownNat' instance available.--- Results are ignored.-traverseNatList_-    :: forall f a ns. Applicative f-    => (forall n. KnownNat n => Proxy n -> f a)-    -> NatList ns-    -> f ()-traverseNatList_ f = go-  where-    go :: forall ms. NatList ms -> f ()-    go = \case-      ØNL       -> pure ()-      n :<# ns -> f n *> go ns---- | The "eliminator" for 'NatList'.  You can think of this as--- a dependently typed analogy for a fold.------ /Since 0.2.1.0/-elimNatList-    :: forall p ns. ()-    => p '[]-    -> (forall m ms. (KnownNat m, KnownNats ms) => Proxy m -> p ms -> p (m ': ms))-    -> NatList ns-    -> p ns-elimNatList z s = \case-    ØNL      -> z-    n :<# ns -> s n (elimNatList z s ns)----- | Utility function for \"mapping\" over each of the 'Nat's in the--- 'NatList'.-mapNatList-    :: (forall n. KnownNat n => Proxy n -> SomeNat)-    -> NatList ns-    -> SomeNats-mapNatList f = runIdentity . traverseNatList (Identity . f)---- | Like 'mapNatList', but avoids the Rank-2 types, so can be used with--- '.' (function composition) and in other situations where 'mapNatList'--- would cause problems.-mapNatList'-    :: (SomeNat -> SomeNat)-    -> SomeNats-    -> SomeNats-mapNatList' f = runIdentity . traverseNatList' (Identity . f)---- | List equivalent of 'someNatVal'.  Convert a list of integers into an--- unknown type-level list of naturals.  Will return 'Nothing' if any of--- the given 'Integer's is negative.------ __Deprecated:__ Use 'toSing' from /singletons/ instead.-someNatsVal :: [Integer] -> Maybe SomeNats-someNatsVal []     = Just (SomeNats ØNL)-someNatsVal (n:ns) = do-    SomeNat  m  <- someNatVal n-    SomeNats ms <- someNatsVal ns-    return $ SomeNats (m :<# ms)-{-# DEPRECATED someNatsVal "Use toSing from the singletons package instead" #-}---- | List equivalent of 'reifyNat'.  Given a list of integers, takes--- a function in an "environment" with a @'NatList' ns@ corresponding to--- the given list, where every @n@ in @ns@ has a 'KnownNat' instance.------ Essentially a continuation-style version of 'SomeNats'.------ Be aware that this also produces @'KnownNat' n@s where @n@ is negative,--- without complaining.  To be consistent, within the library, this--- /should/ be called @reifyNatsPos@; however, the naming choice is for--- consistency with 'reifyNat' from the /reflections/ package.  Use--- 'reifyNats'' for a "safe" version.------ __Deprecated:__ Use 'withSomeSing' from /singletons/ instead.-reifyNats :: [Integer] -> (forall ns. KnownNats ns => NatList ns -> r) -> r-reifyNats []     f = f ØNL-reifyNats (n:ns) f = reifyNat n $ \m ->-                       reifyNats ns $ \ms ->-                         f (m :<# ms)-{-# DEPRECATED reifyNats "Use withSomeSing from the singletons package instead" #-}---- | "Safe" version of 'reifyNats', which will only run the continuation if--- every 'Integer' in the list is non-negative.  If not, then returns--- the given "default" value instead.------ __Deprecated:__ Use 'withSomeSing' from /singletons/ instead.-reifyNats'-    :: [Integer]-    -> r-    -> (forall ns. KnownNats ns => NatList ns -> r)-    -> r-reifyNats' ns d f =-    case someNatsVal ns of-      Just (SomeNats ms) -> f ms-      Nothing            -> d-{-# DEPRECATED reifyNats' "Use withSomeSing from the singletons package instead" #-}---- | Like 'someNatsVal', but will also go ahead and produce 'KnownNat's--- whose integer values are negative.  It won't ever error on producing--- them, but extra care must be taken when using the produced 'SomeNat's.------ __Deprecated:__ Use 'toSing' from /singletons/ instead.-someNatsValPos :: [Integer] -> SomeNats-someNatsValPos ns = reifyNats ns SomeNats-{-# DEPRECATED someNatsValPos "Use toSing from the singletons package instead" #-}---- | Get evidence that the two 'KnownNats' lists are actually the "same"--- list of 'Nat's (that they were instantiated with the same numbers).------ Essentialy runs 'sameNat' over the lists:------ @--- case 'sameNats' ns ms of---   Just 'Refl' -> -- in this branch, GHC recognizes that the two ['Nat']s---                  -- are the same.---   Nothing   -> -- in this branch, they aren't--- @------ __Deprecated:__ Use '%~' from /singletons/ instead.-sameNats-    :: NatList ns-    -> NatList ms-    -> Maybe (ns :~: ms)-sameNats = \case-    ØNL      -> \case-      ØNL      -> Just Refl-      _ :<# _  -> Nothing-    n :<# ns -> \case-      ØNL      -> Nothing-      m :<# ms -> do-        Refl <- sameNat n m-        Refl <- sameNats ns ms-        return Refl-{-# DEPRECATED sameNats "Use (%~) from the singletons package instead" #-}----- | @'KnownSymbols' ss@ is intended to represent that every 'Symbol' in the--- type-level list 'ss' is itself a 'KnownSymbol' (meaning, you can use--- 'symbolVal' to get its corresponding 'String').------ You can use 'symbolsVal' to get the corresponding @['String']@ from--- @'KnownSymbols' ss@.------ For reasons discussed further in the documentation for 'KnownNats', this--- also lets you generate a @'SymbolList' ss@, in order to iterate over the--- type-level list of 'Symbol's and take advantage of their 'KnownSymbol'--- instances.------ __Deprecated:__ Use 'SingI from /singletons/ instead.-class KnownSymbols (ss :: [Symbol]) where-    -- | __Deprecated:__ Use 'fromSing' from /singletons/ instead.-    symbolsVal  :: p ss -> [String]-    -- | __Deprecated:__ Use 'sing from /singletons/ instead.-    symbolsList :: SymbolList ss-{-# DEPRECATED KnownSymbols "Use SingI from the singletons package instead" #-}-{-# DEPRECATED symbolsVal "Use fromSing from the singletons package instead" #-}-{-# DEPRECATED symbolsList "Use sing from the singletons package instead" #-}--instance KnownSymbols '[] where-    symbolsVal  _ = []-    symbolsList    = ØSL--instance (KnownSymbol s, KnownSymbols ss) => KnownSymbols (s ': ss) where-    symbolsVal  _ = symbolVal (Proxy :: Proxy s) : symbolsVal (Proxy :: Proxy ss)-    symbolsList   = Proxy :<$ symbolsList---- | Represents unknown type-level lists of 'Symbol's. It's a 'SymbolList',--- but you don't know what the list contains at compile-time.------ __Deprecated:__ Use 'SomeSing' from /singletons/ instead.-data SomeSymbols :: Type where-    SomeSymbols :: KnownSymbols ss => !(SymbolList ss) -> SomeSymbols-{-# DEPRECATED SomeSymbols "Use SomeSing from the singletons package instead" #-}---- | Singleton-esque type for "traversing" over type-level lists of--- 'Symbol's. Essentially contains a (value-level) list of @'Proxy' n@s,--- but each 'n' has a 'KnownSymbol' instance for you to use.  At runtime--- (after type erasure), is more or less equivalent to a @['String']@.------ Typically generated using 'symbolsList'.------ __Deprecated:__ Use 'Sing' from /singletons/ instead.-data SymbolList :: [Symbol] -> Type where-    ØSL   :: SymbolList '[]-    (:<$) :: (KnownSymbol s, KnownSymbols ss)-          => !(Proxy s) -> !(SymbolList ss) -> SymbolList (s ': ss)-{-# DEPRECATED SymbolList "Use Sing from the singletons package instead" #-}--infixr 5 :<$-deriving instance Show (SymbolList ns)---- | Utility function for traversing over all of the @'Proxy' s@s in--- a 'SymbolList', each with the corresponding 'KnownSymbol' instance--- available.  Gives the the ability to "change" the represented natural--- number to a new one, in a 'SomeSymbol'.------ Can be considered a form of a @Traversal' 'SomeSymbols' 'SomeSymbol'@.-traverseSymbolList-    :: forall f ss. Applicative f-    => (forall s. KnownSymbol s => Proxy s -> f SomeSymbol)-    -> SymbolList ss-    -> f SomeSymbols-traverseSymbolList f = go-  where-    go :: forall ms. SymbolList ms -> f SomeSymbols-    go = \case-      ØSL      -> pure $ SomeSymbols ØSL-      s :<$ ss -> merge <$> f s <*> go ss-    merge :: SomeSymbol -> SomeSymbols -> SomeSymbols-    merge = \case-      SomeSymbol s -> \case-        SomeSymbols ss ->-          SomeSymbols (s :<$ ss)---- | Like 'traverseSymbolList', but literally actually a--- @Traversal' 'SomeSymbols' 'SomeSymbol'@, avoiding the Rank-2 types, so--- is usable with lens-library machinery.-traverseSymbolList'-    :: forall f. Applicative f-    => (SomeSymbol -> f SomeSymbol)-    -> SomeSymbols-    -> f SomeSymbols-traverseSymbolList' f = \case-    SomeSymbols ns' -> traverseSymbolList (f . SomeSymbol) ns'---- | Utility function for traversing over all of the @'Proxy' s@s in--- a 'SymbolList', each with the corresponding 'KnownSymbol' instance--- available. Results are ignored.-traverseSymbolList_-    :: forall f ss. Applicative f-    => (forall s a. KnownSymbol s => Proxy s -> f a)-    -> SymbolList ss-    -> f ()-traverseSymbolList_ f = go-  where-    go :: forall ts. SymbolList ts -> f ()-    go = \case-      ØSL      -> pure ()-      s :<$ ss -> f s *> go ss---- | Utility function for \"mapping\" over each of the 'Symbol's in the--- 'SymbolList'.-mapSymbolList-    :: (forall s. KnownSymbol s => Proxy s -> SomeSymbol)-    -> SymbolList ss-    -> SomeSymbols-mapSymbolList f = runIdentity . traverseSymbolList (Identity . f)---- | Like 'mapSymbolList', but avoids the Rank-2 types, so can be used with--- '.' (function composition) and in other situations where 'mapSymbolList'--- would cause problems.-mapSymbolList'-    :: (SomeSymbol -> SomeSymbol)-    -> SomeSymbols-    -> SomeSymbols-mapSymbolList' f = runIdentity . traverseSymbolList' (Identity . f)---- | The "eliminator" for 'SymbolList'.  You can think of this as--- a dependently typed analogy for a fold.------ /Since 0.2.1.0/-elimSymbolList-    :: forall p ss. ()-    => p '[]-    -> (forall t ts. (KnownSymbol t, KnownSymbols ts) => Proxy t -> p ts -> p (t ': ts))-    -> SymbolList ss-    -> p ss-elimSymbolList z s = \case-    ØSL      -> z-    n :<$ ns -> s n (elimSymbolList z s ns)----- | List equivalent of 'someNatVal'.  Convert a list of integers into an--- unknown type-level list of naturals.  Will return 'Nothing' if any of--- the given 'Integer's is negative.------ __Deprecated:__ Use 'toSing' from /singletons/ instead.-someSymbolsVal :: [String] -> SomeSymbols-someSymbolsVal []     = SomeSymbols ØSL-someSymbolsVal (s:ss) =-    case someSymbolVal s of-      SomeSymbol t ->-        case someSymbolsVal ss of-          SomeSymbols ts ->-            SomeSymbols (t :<$ ts)-{-# DEPRECATED someSymbolsVal "Use toSing from the singletons package instead" #-}---- | List equivalent of 'reifyNat'.  Given a list of integers, takes--- a function in an "environment" with a @'SymbolList' ss@ corresponding to--- the given list, where every @s@ in @ss@ has a 'KnownSymbol' instance.------ Essentially a continuation-style version of 'SomeSymbols'.------ __Deprecated:__ Use 'withSomeSing' from /singletons/ instead.-reifySymbols :: [String]-             -> (forall ss. KnownSymbols ss => SymbolList ss -> r)-             -> r-reifySymbols []     f = f ØSL-reifySymbols (s:ss) f = reifySymbol s $ \t ->-                          reifySymbols ss $ \ts ->-                            f (t :<$ ts)-{-# DEPRECATED reifySymbols "Use withSomeSing from the singletons package instead" #-}----- | Get evidence that the two 'KnownSymbols' lists are actually the "same"--- list of 'Symboles's (that they were instantiated with the same strings).------ Essentialy runs 'sameSymbol' over the lists:------ @--- case 'sameSymbols' ns ms of---   Just 'Refl' -> -- in this branch, GHC recognizes that the---                  -- two ['Symbol']s are the same---   Nothing   -> -- in this branch, they aren't--- @------ __Deprecated:__ Use '%~' from /singletons/ instead.-sameSymbols-    :: SymbolList ns-    -> SymbolList ms-    -> Maybe (ns :~: ms)-sameSymbols = \case-    ØSL      -> \case-      ØSL      -> Just Refl-      _ :<$ _  -> Nothing-    s :<$ ss -> \case-      ØSL      -> Nothing-      t :<$ ts -> do-        Refl <- sameSymbol s t-        Refl <- sameSymbols ss ts-        return Refl-{-# DEPRECATED sameSymbols "Use (%~) from the singletons package instead" #-}-
src/GHC/TypeLits/Witnesses.hs view
@@ -1,307 +1,434 @@-{-# LANGUAGE CPP                 #-}-{-# LANGUAGE ConstraintKinds     #-}-{-# LANGUAGE FlexibleContexts    #-}-{-# LANGUAGE PolyKinds           #-}-{-# LANGUAGE RankNTypes          #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators       #-}-#if __GLASGOW_HASKELL__ >= 806-{-# LANGUAGE NoStarIsType #-}-#endif+{-# LANGUAGE ConstraintKinds           #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleContexts          #-}+{-# LANGUAGE GADTs                     #-}+{-# LANGUAGE LambdaCase                #-}+{-# LANGUAGE PatternSynonyms           #-}+{-# LANGUAGE RankNTypes                #-}+{-# LANGUAGE ScopedTypeVariables       #-}+{-# LANGUAGE StandaloneDeriving        #-}+{-# LANGUAGE TypeInType                #-}+{-# LANGUAGE TypeOperators             #-}+{-# LANGUAGE ViewPatterns              #-}  -- | -- Module      : GHC.TypeLits.Witnesses--- Description : Instance witnesses for various arithmetic operations on---               GHC TypeLits. -- Copyright   : (c) Justin Le 2016 -- License     : MIT -- Maintainer  : justin@jle.im -- Stability   : unstable -- Portability : non-portable ----- This module provides witnesses for instances that result from the--- various arithmetic operations on GHC TypeLits 'Nat' types.  In general,--- if you have @'KnownNat' n@, GHC can't infer @'KnownNat' (n + 1)@; and if--- you have @'KnownNat' m@, as well, GHC can't infer @'KnownNat' (n + m)@.+-- This module essentially provides a lightweight subset of the+-- /singletons/ library specifically for 'Nat' and 'Symbol', from+-- "GHC.TypeLits". ----- This can be extremely annoying when dealing with libraries and--- applications where one regularly adds and subtracts type-level nats and--- expects 'KnownNat' instances to follow.  For example, vector--- concatenation of length-encoded vector types can be:+-- Its main functionality is for first-class manipulation of 'KnownNat' and+-- 'KnownSymbol' constraints.  For example, in general, if you have+-- @'KnownNat' n@, GHC can't infer @'KnownNat' (n + 1)@.  And, if you have+-- both @'KnownNat' n@ and @'KnownNat' m@, GHC can't infer @'KnownNat (n+-- + m)@. --+-- This can be annoying when dealing with libraries and applications where+-- one regularly adds and subtracts type-level nats and expects 'KnownNat'+-- instances to follow.  For example, vector concatenation of+-- length-encoded vector types can be:+-- -- @ -- concat :: ('KnownNat' n, 'KnownNat' m) => Vector n a -> Vector m a -> Vector (n + m) a -- @ -- -- But, now @n + m@ does not have a 'KnownNat' instance...which makes--- operations like this extremely less useful!+-- operations like this much less useful. ----- At the highest level, this module can be used with 'withNatOp':+-- Usually, the easiest way to get around this is to use a typechecker+-- plugin, like+-- <https://hackage.haskell.org/package/ghc-typelits-knownnat>.  However,+-- we can do this without the help of a typechecker plugin using+-- first-class values, at the cost of some increased verbosity. --+-- We introduce @'SNat' n@, which is a term-level witness of knownnat-ness+-- that can be manipulated as a first-class value.+--+-- If we have @'KnownNat' n@, we can construct an @'SNat' n@:+-- -- @--- getDoubled :: forall n. 'KnownNat' n => 'Proxy' n -> 'Integer'--- getDoubled p = 'withNatOp' ('%*') p ('Proxy' :: 'Proxy' 2) $---     natVal ('Proxy' :: 'Proxy' (n * 2))+-- 'SNat' :: KnownNat n -> SNat n -- @ ----- With the final argument of 'withNatOp', you can provide a result--- computed in an environment where @n * 2@ is indeed an instance of--- 'KnownNat'.------ For more complex usage, you can directly manipulate witnesses and then--- use them via pattern matching:+-- Furthermore, if we have an @'SNat' n@, we can /pattern match/ on the+-- 'SNat' constructor to get a @'KnownNat' n@ constraint: -- -- @--- let pn = 'natDict' ('Proxy' :: 'Proxy' n)---     p1 = 'natDict' ('Proxy' :: 'Proxy' 1)---     p2 = 'natDict' ('Proxy' :: 'Proxy' 2)--- in  case pn '%*' p2 '%+' p1 of---       'Dict' -> 'natVal' ('Proxy' :: 'Proxy' (n * 2 + 1))+-- myFunc :: SNat n -> Bool+-- myFunc SNat = ...  -- in this body, we have `KnownNat n` -- @ ----- In the branch of the case statement, @n * 2 + 1@ indeed has a 'KnownNat'--- instance.+-- So if we have @'KnownNat' n@ and @'KnownNat' m@, we can get @'KnownNat'+-- (n + m)@ by using '%+', which adds together 'SNat's: ----- Note that the operators have appropriate fixities to mimic value-level--- arithmetic operations.+-- @+-- case (SNat :: SNat n) %+ (SNat :: SNat m) of+--   SNat -> -- in this branch, we have `KnownNat (n + m)`+-- @ ----- __WARNING__: '%-' and 'entailSub' are is implemented in a way such--- that /negative/ 'KnownNat's are produced without any errors.  The--- production of witnesses and entailments will hold, but be aware that any--- functions that rely on 'KnownNat' instances to be non-negative can--- potentially break.+-- Note that this module converts between 'SNat' and 'Natural', and not+-- 'SNat' and 'Integer', in "GHC.TypeNats"-style. -----module GHC.TypeLits.Witnesses-  {-# DEPRECATED "Use singletons package instead" #-} (-  -- * Singletons-  -- $singletons-  -- * High level wrapper-    withNatOp-  -- * Direct witnesses-  , natDict-  , dictNatVal-  -- * Witness generators+-- Of course, all of this functionality is provided by the /singletons/+-- library, in "Data.Singletons.TypeLits".  This module can be useful if+-- you want a lightweight alternative without the full might of+-- /singletons/.  The main benefit of the /singletons/ library is providing+-- a unified interface for singletons of /all/ different kinds/types, and+-- not just 'Natural' and 'String'.+module GHC.TypeLits.Witnesses (+  -- * Nats+    SNat(..)+  , SomeNat(SomeNat_)+  , Natural(FromSNat)+  , fromSNat+  , withKnownNat+  , withSomeNat+  , toSomeNat+  -- ** Operations   , (%+)   , (%-)+  , minusSNat+  , minusSNat_   , (%*)   , (%^)-  -- * Entailments-  , entailAdd-  , entailSub-  , entailMul-  , entailExp+  -- ** Compare+  , (%<=?)+  , sCmpNat+  -- ** Unsafe+  , unsafeLiftNatOp1+  , unsafeLiftNatOp2+  -- * Symbols+  , SSymbol(..)+  , SomeSymbol(SomeSymbol_)+  , pattern FromSSymbol+  , fromSSymbol+  , withKnownSymbol+  , withSomeSymbol+  , toSomeSymbol   ) where -import           Data.Constraint+import           Data.GADT.Compare+import           Data.GADT.Show import           Data.Proxy-import           Data.Reflection-import           GHC.TypeLits+import           Data.Type.Equality+import           GHC.Natural+import           GHC.TypeLits hiding         (natVal, someNatVal)+import           GHC.TypeLits.Compare hiding ((%<=?))+import           GHC.TypeNats import           Unsafe.Coerce+import qualified GHC.TypeLits.Compare        as Comp --- $singletons------ All of the functionality in this module can be subsumed by the--- /singletons/ package, by utilizing:------   * "Data.Singletons"---   * "Data.Singletons.TypeLits"---   * "Data.Singletons.Prelude.Num"------ This module is left in this package as an alternative for those who--- might, for some reason, not want to add a /singletons/ dependency to--- their project.  However, if you do much at the type level, using the--- /singletons/ library is much preferred, as it provides a unifed--- interface for all of the functionality here, generalized to other kinds--- besides 'Nat'.------ For all functions in this module, a /singletons/ equivalent is included--- for help migrating.------ In general:---------   * The /singletons/ type @'Sing' n@ (or its equivalent, @'SNat' n@)---     subsumes both @'Proxy' n@ and @'Dict' ('KnownNat' n)@.  You can---     replace both @'Proxy' n@ and @'Dict' ('KnownNat' n)@ with @'SNat' n@---     to move to singletons style.------   * 'dictNatVal' and 'natVal' are both just 'fromSing'.------   * Replace '%+', '%-', and '%*' with their /singletons/---     equivalents, '%:+', '%:-', and '%:*' from---     "Data.Singletons.Prelude.Num".  Note that the current version of---     /singletons/ does not have an equivalent for '%^'.+-- | An @'SNat' n@ is a witness for @'KnownNat' n@. -----   * Use 'withKnownNat' from /singletons/ (or just pattern match on---     'SNat') to get a 'KnownNat' instance from a @'SNat' n@, the same way---     you'd get one from a 'Dict'.+-- This means that if you pattern match on the 'SNat' constructor, in that+-- branch you will have a @'KnownNat' n@ constraint. -----   * The high-level combinator 'withNatOp' can simply be replaced with---     applying your singleton functions ('%+' etc.) to 'SNat' values, and---     pattern matching on the result, or using 'withKnownNat' on the result.+-- @+-- myFunc :: SNat n -> Bool+-- myFunc SNat = ...  -- in this body, we have `KnownNat n`+-- @ --+-- This is essentially a singleton for 'Nat', and stands in for the+-- /singletons/ 'SNat' and 'Data.Singleton.Sing' types.+data SNat n = KnownNat n => SNat --- | Create a 'Dict' witness for @'KnownNat' n@.------ Not necessary with /singletons/, as @'SNat' n@ stands in for both--- @'Proxy' n@ and @'Dict' ('KnownNat' n)@.-natDict :: KnownNat n => p n -> Dict (KnownNat n)-natDict _ = Dict+deriving instance Eq (SNat n)+deriving instance Ord (SNat n) --- | Get the 'Integer' from the 'KnownNat' instance witnessed by the--- 'Dict'.------ With /singletons/, this is 'fromSing', which takes an @'SNat' n@ and--- returns an 'Integer'.-dictNatVal :: forall n. Dict (KnownNat n) -> Integer-dictNatVal Dict = natVal (Proxy :: Proxy n)+instance Show (SNat n) where+    showsPrec d x@SNat = showParen (d > 10) $+      showString "SNat @" . showsPrec 11 (fromSNat x) -infixl 6 %+-infixl 6 %--infixl 7 %*-infixr 8 %^+instance GShow SNat where+    gshowsPrec = showsPrec --- | Given witnesses for @'KnownNat' n@ and @'KnownNat' m@, generates--- a witness for @'KnownNat' (n + m)@.+instance TestEquality SNat where+    testEquality (SNat :: SNat n) (SNat :: SNat m) =+      flip fmap (sameNat (Proxy :: Proxy n) (Proxy :: Proxy m)) $ \case+        Refl -> Refl++instance GEq SNat where+    geq = testEquality++instance GCompare SNat where+    gcompare x = cmpNatGOrdering . sCmpNat x++data SomeNat__ = forall n. SomeNat__ (SNat n)++-- | A useful pattern synonym for matching on a 'SomeNat' as if it+-- contained an @'SNat' n@, and not a @'Proxy' n@ as it exists in+-- "GHC.TypeLits". ----- Follows proper association and fixity for usage with other similar--- operators.+-- A layer of compatibility letting us use the original 'SomeNat' type in+-- a way that works well with 'SNat'. ----- With /singletons/, this is '%:+' from "Data.Singletons.Prelude.Num".-(%+) :: forall n m. Dict (KnownNat n) -> Dict (KnownNat m) -> Dict (KnownNat (n + m))-Dict %+ Dict = mapDict entailAdd (Dict :: Dict (KnownNat n, KnownNat m))+-- This stands in for the /singletons/ 'Data.Singleton.SomeSing' constructor.+pattern SomeNat_ :: SNat n -> SomeNat+pattern SomeNat_ x <- ((\case SomeNat (Proxy :: Proxy n) -> SomeNat__ (SNat :: SNat n)) -> SomeNat__ x)+  where+    SomeNat_ (SNat :: SNat n) = SomeNat (Proxy :: Proxy n)+{-# COMPLETE SomeNat_ #-} --- | Given witnesses for @'KnownNat' n@ and @'KnownNat' m@, generates--- a witness for @'KnownNat' (n - m)@.+-- | A useful pattern synonym for matching on a 'Natural' as if it "were"+-- a 'SNat': ----- Note that this is implemented in a way such that /negative/ 'KnownNat's--- are produced without any errors.+-- @+-- myFunc :: Natural -> Bool+-- myFunc (FromSNat x) = ...  -- x is `SNat n`, with `n` coming from the input+-- @ ----- Follows proper association and fixity for usage with other similar--- operators.+-- It can be used as a function, as well, to convert an @'SNat' n@ back+-- into the 'Natural' that it represents. ----- With /singletons/, this is '%:-' from "Data.Singletons.Prelude.Num".-(%-) :: forall n m. Dict (KnownNat n) -> Dict (KnownNat m) -> Dict (KnownNat (n - m))-Dict %- Dict = mapDict entailSub (Dict :: Dict (KnownNat n, KnownNat m))+-- This stands in for the /singletons/ 'Data.Singleton.FromSing' pattern synonym.+pattern FromSNat :: SNat n -> Natural+pattern FromSNat x <- ((\i -> withSomeNat i SomeNat_) -> SomeNat_ x)+  where+    FromSNat = fromSNat+{-# COMPLETE FromSNat #-} --- | Given witnesses for @'KnownNat' n@ and @'KnownNat' m@, generates--- a witness for @'KnownNat' (n * m)@.+-- | Given an @'SNat' n@ and a value that would require a @'KnownNat' n@+-- instance, create that value. ----- Follows proper association and fixity for usage with other similar--- operators.+-- This stands in for the function of the same name from+-- "Data.Singletons.TypeLits".+withKnownNat :: SNat n -> (KnownNat n => r) -> r+withKnownNat SNat x = x++-- | Promote ("reify") a 'Natural' to an @'SNat' n@, by providing+-- a continuation that would handle it in a way that is polymorphic over+-- all possible @n@. ----- With /singletons/, this is '%:*' from "Data.Singletons.Prelude.Num".-(%*) :: forall n m. Dict (KnownNat n) -> Dict (KnownNat m) -> Dict (KnownNat (n * m))-Dict %* Dict = mapDict entailMul (Dict :: Dict (KnownNat n, KnownNat m))+-- This stands in the /singletons/ 'Data.Singleton.withSomeSing' function.+withSomeNat :: Natural -> (forall n. SNat n -> r) -> r+withSomeNat (someNatVal->SomeNat (Proxy :: Proxy n)) x = x (SNat :: SNat n) --- | Given witnesses for @'KnownNat' n@ and @'KnownNat' m@, generates--- a witness for @'KnownNat' (n ^ m)@.+-- | Promote ("reify") a 'Natural' to an @'SNat' n@ existentially hidden+-- inside a 'SomeNat'.  To use it, pattern match using 'SomeNat_'. ----- Follows proper association and fixity for usage with other similar--- operators.-(%^) :: forall n m. Dict (KnownNat n) -> Dict (KnownNat m) -> Dict (KnownNat (n ^ m))-Dict %^ Dict = mapDict entailExp (Dict :: Dict (KnownNat n, KnownNat m))+-- This stands in the /singletons/ 'Data.Singleton.toSomeSing' function.+toSomeNat :: Natural -> SomeNat+toSomeNat = someNatVal --- | A high-level the interface of this module.  Give it one of--- the witness-generating operators on 'KnownNat's in this module ('%+',--- '%-', '%*', or '%^'), two 'Proxy's containing the 'KnownNat's to--- be modified, and receive an environment where the result of the--- operation (applied to the 'KnownNat's) has a 'KnownNat' instance.+-- | Convert ("reflect") an 'SNat' back into the 'Natural' it represents. ----- For example, with+-- This stands in the /singletons/ 'Data.Singleton.fromSing' function.+fromSNat :: SNat n -> Natural+fromSNat x@SNat = natVal x++-- | Lift a unary operation to act on an @'SNat' n@ that returns an @'SNat'+-- m@.  The function given must properly describe the relationship between+-- @n@ and @m@. --+-- For example:+-- -- @--- 'withNatOp' ('%+') ('Proxy' :: 'Proxy' n) ('Proxy' :: 'Proxy' 1) r+-- double :: SNat n -> SNat (n * 2)+-- double = unsafeLiftNatOp1 (*2) -- @ ----- in @r@, @n + 1@ has a 'KnownNat' instance:+-- The correctness of the relationship is not checked, so be aware that+-- this can cause programs to break.+unsafeLiftNatOp1+    :: (Natural -> Natural)+    -> SNat n+    -> SNat m+unsafeLiftNatOp1 f x = withSomeNat (f (fromSNat x)) unsafeCoerce++-- | Lift a binary operation to act on an @'SNat' n@ and @'SNat' m@ that+-- returns an @'SNat' o@.  The function given must properly describe the+-- relationship between @n@, @m@, and @o@. --+-- For example:+-- -- @--- 'withNatOp' ('%+') ('Proxy' :: 'Proxy' n) ('Proxy' :: 'Proxy' 1) $---     'natVal' ('Proxy' :: 'Proxy' (n + 1))--- -- => will return the 'Integer' correpsonding to n + 1+-- multiply :: SNat n -> SNat m -> SNat (n * m)+-- multiply = unsafeLiftNatOp2 (*) -- @ ----- Normally, if @n@ is a 'KnownNat' instance, it is not in general--- inferrable that @n + 1@ also has a 'KnownNat' instance.  This combinator--- makes it so.+-- The correctness of the relationship is not checked, so be aware that+-- this can cause programs to break.+unsafeLiftNatOp2+    :: (Natural -> Natural -> Natural)+    -> SNat n+    -> SNat m+    -> SNat o+unsafeLiftNatOp2 f x y = withSomeNat (f (fromSNat x) (fromSNat y)) unsafeCoerce++-- | Addition of 'SNat's. ----- For multiple operations on values, this can be chained:+-- This also will provide the correct 'KnownNat' instance for @'SNat' (n+-- + m)@, so can be used as a way to "add" 'KnownNat' instances. ----- @--- 'withNatOp' ('%*') ('Proxy' :: 'Proxy' n) ('Proxy' :: 'Proxy' 2) $---   'withNatOp' ('%+') ('Proxy' :: 'Proxy' (n*2)) ('Proxy' :: 'Proxy' 1) $---     'natVal' ('Proxy' :: 'Proxy' (n * 2 + 1))--- @+-- This stands in for the function with the same name from+-- "Data.Singletons.Prelude.Num".+(%+) :: SNat n -> SNat m -> SNat (n + m)+(%+) = unsafeLiftNatOp2 (+)++-- | Subtraction of 'SNat's.  Note that this is unsafe, as will trigger+-- a run-time underflow if @m@ is bigger than @n@ even though it will always+-- succeed at compiletime. ----- But, at this point, it's easier and simpler to just directly use the--- operators and pattern match:+-- This also will provide the correct 'KnownNat' instance for @'SNat' (n+-- - m)@, so can be used as a way to "subtract" 'KnownNat' instances. ----- @--- let pn = 'natDict' ('Proxy' :: 'Proxy' n)---     p1 = 'natDict' ('Proxy' :: 'Proxy' 1)---     p2 = 'natDict' ('Proxy' :: 'Proxy' 2)--- in  case pn '%*' p2 '%+' p1 of---       'Dict' -> 'natVal' ('Proxy' :: 'Proxy' (n * 2 + 1))--- @+-- This stands in for the function with the same name from+-- "Data.Singletons.Prelude.Num".+(%-) :: SNat n -> SNat m -> SNat (n - m)+(%-) = unsafeLiftNatOp2 (-)++-- | A safe version of '%-': it will return 'Left' if @n@ is less than @m@+-- (with a witness that it is), or else return the subtracted 'SNat' in+-- 'Right' in a way that is guarunteed to not have runtime underflow.+minusSNat+    :: SNat n+    -> SNat m+    -> Either (CmpNat n m :~: 'LT) (SNat (n - m))+minusSNat (fromSNat->x) (fromSNat->y) = case minusNaturalMaybe x y of+    Nothing -> Left (unsafeCoerce Refl)+    Just z  -> withSomeNat z unsafeCoerce++-- | A version of 'minusSNat' that just returns a 'Maybe'.+minusSNat_ :: SNat n -> SNat m -> Maybe (SNat (n - m))+minusSNat_ x = either (const Nothing) Just . minusSNat x++-- | Addition of 'SNat's. ----- (Note that associativity and fixity for the witness-generating operators--- are set to match that of normal addition and multiplication, etc.)+-- This also will provide the correct 'KnownNat' instance for @'SNat' (n+-- * m)@, so can be used as a way to "multiply" 'KnownNat' instances. ----- With /singletons/, @'withNatOp' f x y@ is @'withKnownNat' (f x y)@.+-- This stands in for the function with the same name from+-- "Data.Singletons.Prelude.Num".+(%*) :: SNat n -> SNat m -> SNat (n - m)+(%*) = unsafeLiftNatOp2 (*)++-- | Exponentiation of 'SNat's. ----- So, instead of+-- This also will provide the correct 'KnownNat' instance for @'SNat' (n+-- ^ m)@, so can be used as a way to "exponentiate" 'KnownNat' instances. --+-- This stands in for the function with the same name from+-- "Data.Singletons.TypeLits".+(%^) :: SNat n -> SNat m -> SNat (n ^ m)+(%^) = unsafeLiftNatOp2 (^)++-- | Compare @n@ and @m@, categorizing them into one of the constructors of+-- ':<=?'.+(%<=?) :: SNat n -> SNat m -> n :<=? m+x@SNat %<=? y@SNat = x Comp.%<=? y++-- | Compare @n@ and @m@, categorizing them into one of the constructors of+-- 'SCmpNat'.+sCmpNat :: SNat n -> SNat m -> SCmpNat n m+sCmpNat x@SNat y@SNat = cmpNat x y++-- | An @'SSymbol' n@ is a witness for @'KnownSymbol' n@.+--+-- This means that if you pattern match on the 'SSymbol' constructor, in that+-- branch you will have a @'KnownSymbol' n@ constraint.+-- -- @--- 'withNatOp' ('%+') ('Proxy' :: 'Proxy' n) ('Proxy' :: 'Proxy' 1) $---     'natVal' ('Proxy' :: 'Proxy' (n + 1))+-- myFunc :: SSymbol n -> Bool+-- myFunc SSymbol = ...  -- in this body, we have `KnownSymbol n` -- @ ----- You can just use+-- This is essentially a singleton for 'Symbol', and stands in for the+-- /singletons/ 'SSymbol' and 'Data.Singleton.Sing' types.+data SSymbol n = KnownSymbol n => SSymbol++deriving instance Eq (SSymbol n)+deriving instance Ord (SSymbol n)++instance Show (SSymbol n) where+    showsPrec d x@SSymbol = showParen (d > 10) $+      showString "SSymbol @" . showsPrec 11 (fromSSymbol x)++instance GShow SSymbol where+    gshowsPrec = showsPrec++instance TestEquality SSymbol where+    testEquality (SSymbol :: SSymbol n) (SSymbol :: SSymbol m) =+      flip fmap (sameSymbol (Proxy :: Proxy n) (Proxy :: Proxy m)) $ \case+        Refl -> Refl++instance GEq SSymbol where+    geq = testEquality++instance GCompare SSymbol where+    gcompare x y = case compare (fromSSymbol x) (fromSSymbol y) of+      LT -> GLT+      EQ -> unsafeCoerce GEQ+      GT -> GGT++data SomeSymbol__ = forall n. SomeSymbol__ (SSymbol n)++-- | A useful pattern synonym for matching on a 'SomeSymbol' as if it+-- contained an @'SSymbol' n@, and not a @'Proxy' n@ as it exists in+-- "GHC.TypeLits". --+-- A layer of compatibility letting us use the original 'SomeSymbol' type in+-- a way that works well with 'SSymbol'.+--+-- This stands in for the /singletons/ 'Data.Singleton.SomeSing' constructor.+pattern SomeSymbol_ :: SSymbol n -> SomeSymbol+pattern SomeSymbol_ x <- ((\case SomeSymbol (Proxy :: Proxy n) -> SomeSymbol__ (SSymbol :: SSymbol n)) -> SomeSymbol__ x)+  where+    SomeSymbol_ (SSymbol :: SSymbol n) = SomeSymbol (Proxy :: Proxy n)+{-# COMPLETE SomeSymbol_ #-}++-- | A useful pattern synonym for matching on a 'String' as if it "were"+-- a 'SSymbol':+-- -- @--- 'withKnownNat' ('SNat' @n) ('SNat @1) $---     'natVal' ('Proxy' :: 'Proxy' (n + 1))+-- myFunc :: String -> Bool+-- myFunc (FromSSymbol x) = ...  -- x is `SSymbol n`, with `n` coming from the input -- @ ----- 'natVal' can of course be replaced with 'fromSing'.+-- It can be used as a function, as well, to convert an @'SSymbol' n@ back+-- into the 'String' that it represents. ---withNatOp-    :: (KnownNat n, KnownNat m)-    => (Dict (KnownNat n) -> Dict (KnownNat m) -> Dict (KnownNat q))-    -> p n-    -> p m-    -> (KnownNat q => r)-    -> r-withNatOp op x y r = case natDict x `op` natDict y of-                       Dict -> r---- | An entailment for addition of 'KnownNat' instances.-entailAdd :: forall n m. (KnownNat n, KnownNat m) :- KnownNat (n + m)-entailAdd = Sub $-  reifyNat (natVal (Proxy :: Proxy n) + natVal (Proxy :: Proxy m)) $ \p ->-    unsafeCoerce (natDict p)+-- This stands in for the /singletons/ 'Data.Singleton.FromSing' pattern synonym, except+-- it matches on a 'String' instead of a 'Data.Text.Text'.+pattern FromSSymbol :: SSymbol n -> String+pattern FromSSymbol x <- ((\i -> withSomeSymbol i SomeSymbol_) -> SomeSymbol_ x)+  where+    FromSSymbol = fromSSymbol+{-# COMPLETE FromSSymbol #-} --- | An entailment for subtraction of 'KnownNat' instances.+-- | Given an @'SSymbol' n@ and a value that would require a @'KnownSymbol' n@+-- instance, create that value. ----- Note that this is implemented in a way such that /negative/ 'KnownNat's--- are produced without any errors.-entailSub :: forall n m. (KnownNat n, KnownNat m) :- KnownNat (n - m)-entailSub = Sub $-  reifyNat (natVal (Proxy :: Proxy n) - natVal (Proxy :: Proxy m)) $ \p ->-    unsafeCoerce (natDict p)+-- This stands in for the function of the same name from+-- "Data.Singletons.TypeLits".+withKnownSymbol :: SSymbol n -> (KnownSymbol n => r) -> r+withKnownSymbol SSymbol x = x --- | An entailment for multiplication of 'KnownNat' instances.-entailMul :: forall n m. (KnownNat n, KnownNat m) :- KnownNat (n * m)-entailMul = Sub $-  reifyNat (natVal (Proxy :: Proxy n) * natVal (Proxy :: Proxy m)) $ \p ->-    unsafeCoerce (natDict p)+-- | Promote ("reify") a 'String' to an @'SSymbol' n@, by providing+-- a continuation that would handle it in a way that is polymorphic over+-- all possible @n@.+--+-- This stands in the /singletons/ 'Data.Singleton.withSomeSing' function, except it takes+-- a 'String' instead of 'Data.Text.Text'.+withSomeSymbol :: String -> (forall n. SSymbol n -> r) -> r+withSomeSymbol (someSymbolVal->SomeSymbol (Proxy :: Proxy n)) x = x (SSymbol :: SSymbol n) --- | An entailment for exponentiation of 'KnownNat' instances.-entailExp :: forall n m. (KnownNat n, KnownNat m) :- KnownNat (n ^ m)-entailExp = Sub $-  reifyNat (natVal (Proxy :: Proxy n) ^ natVal (Proxy :: Proxy m)) $ \p ->-    unsafeCoerce (natDict p)+-- | Promote ("reify") a 'String' to an @'SSymbol' n@ existentially hidden+-- inside a 'SomeNat'.  To use it, pattern match using 'SomeSymbol_'.+--+-- This stands in the /singletons/ 'Data.Singleton.toSomeSing' function, except it takes+-- a 'String' instead of 'Data.Text.Text'.+toSomeSymbol :: String -> SomeSymbol+toSomeSymbol = someSymbolVal +-- | Convert ("reflect") an 'SSymbol' back into the 'String' it represents.+--+-- This stands in the /singletons/ 'Data.Singleton.fromSing' function, except it returns+-- a 'String' instead of 'Data.Text.Text'.+fromSSymbol :: SSymbol n -> String+fromSSymbol x@SSymbol = symbolVal x
typelits-witnesses.cabal view
@@ -1,40 +1,26 @@--- This file has been generated from package.yaml by hpack version 0.28.2.+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.31.1. -- -- see: https://github.com/sol/hpack ----- hash: 49b45270e83bf287fa91eedadcbf979e2b8e5438d6ec9adaa6e6fea22183f1a0+-- hash: 8a6351c34d982cd0199ea26cf5f6378e136998abb7019115d627268f8977bdda  name:           typelits-witnesses-version:        0.3.0.3+version:        0.4.0.0 synopsis:       Existential witnesses, singletons, and classes for operations on GHC TypeLits-description:    Provides witnesses for 'KnownNat' and 'KnownSymbol'-                instances for various operations on GHC TypeLits - in-                particular, the arithmetic operations defined in-                "GHC.TypeLits", and also for type-level lists of-                'KnownNat' and 'KnownSymbol' instances.-                .-                This is useful for situations where you have-                @'KnownNat' n@, and you want to prove to GHC-                @'KnownNat' (n + 3)@, or @'KnownNat' (2*n + 4)@, or when-                constraints on the lower or upper limits of @n@ are-                needed.-                .-                It's also useful for when you want to work with type-                level lists of 'KnownNat' or 'KnownSymbol' instances and-                singletons for traversing them, and be able to apply-                analogies of 'natVal' and 'symbolVal' to lists with-                analogies for 'SomeNat' and 'SomeSymbol'.-                .-                Note that most of the functionality in this library can-                be reproduced in a more generic way using the great-                <https://hackage.haskell.org/package/singletons singletons>-                library.  The versions here are provided as a "plumbing-                included" alternative that makes some commonly found-                design patterns involving GHC's TypeLits functionality a-                little smoother, especially when working with external-                libraries or GHC TypeLit's Nat comparison API.+description:    This library contains:                 .-                See README for more information.+                *   A small specialized subset of the *singletons* library as it pertains to+                    `Nat` and `Symbol`, for when you need some simple functionality without+                    wanting to invoke the entire *singletons* library.+                *   Operations for manipulating these singletons and `KnownNat` and+                    `KnownSymbol` instances, such as addition and multiplication of+                    singletons/`KnownNat` instances.+                *   Operations for the comparison of `Nat`s in a way that works well with+                    *GHC.TypeLits*'s different comparison systems.  This is helpful for+                    bridging together libraries that use different systems; this functionality+                    is not yet provided by *singletons*. category:       Data homepage:       https://github.com/mstksg/typelits-witnesses author:         Justin Le@@ -42,12 +28,11 @@ copyright:      (c) Justin Le 2018 license:        MIT license-file:   LICENSE-tested-with:    GHC>=8.0 && <8.8+tested-with:    GHC>=8.2 && <8.8 build-type:     Simple-cabal-version:  >= 1.10 extra-source-files:-    CHANGELOG.md     README.md+    CHANGELOG.md  source-repository head   type: git@@ -55,16 +40,14 @@  library   exposed-modules:-      GHC.TypeLits.Witnesses-      GHC.TypeLits.List       GHC.TypeLits.Compare+      GHC.TypeLits.Witnesses   other-modules:       Paths_typelits_witnesses   hs-source-dirs:       src-  ghc-options: -Wall+  ghc-options: -Wall -Wredundant-constraints -Werror=incomplete-patterns -Wcompat   build-depends:-      base >=4.7 && <5-    , constraints-    , reflection >=2+      base >=4.10 && <5+    , dependent-sum   default-language: Haskell2010