Moduleghc-typelits-knownnat-0.7.12Haskell2010
GHC.TypeLits.KnownNat
Some "magic" classes and instances to get the GHC.TypeLits.KnownNat.Solver type checker plugin working.
Usage
Let's say you defined a closed type family Max:
import Data.Type.Bool (If)
import GHC.TypeLits
type family Max (a :: Nat) (b :: Nat) :: Nat where
Max 0 b = b
Max a b = If (a <=? b) b a
if you then want the GHC.TypeLits.KnownNat.Solver to solve KnownNat
constraints over Max, given just KnownNat constraints for the arguments
of Max, then you must define:
{-# LANGUAGE DataKinds, FlexibleInstances, GADTs, KindSignatures,
MultiParamTypeClasses, ScopedTypeVariables, TemplateHaskell,
TypeApplications, TypeFamilies, TypeOperators,
UndecidableInstances #-}
import Data.Proxy (Proxy (..))
import GHC.TypeLits.KnownNat
instance (KnownNat a, KnownNat b) => KnownNat2 $(nameToSymbol ''Max) a b where
natSing2 = let x = natVal (Proxy a)
y = natVal (Proxy b)
z = max x y
in SNatKn z
{-# INLINE natSing2 #-}
FAQ
1. GHC.TypeLits.KnownNat.Solver does not seem to find the corresponding KnownNat2 instance for my type-level operation
At the Core-level, GHCs internal mini-Haskell, type families that only have a single equation are treated like type synonyms.
For example, let's say we defined a closed type family Max:
import Data.Type.Bool (If)
import GHC.TypeLits
type family Max (a :: Nat) (b :: Nat) :: Nat where
Max a b = If (a <=? b) b a
Now, a Haskell-level program might contain a constraint
KnownNat (Max a b)
, however, at the Core-level, this constraint is expanded to:
KnownNat (If (a <=? b) b a)
GHC.TypeLits.KnownNat.Solver never sees any reference to the Max type
family, so it will not look for the corresponding KnownNat2 instance either.
To fix this, ensure that your type-level operations always have at
least two equations. For Max this means we have to redefine it as:
type family Max (a :: Nat) (b :: Nat) :: Nat where
Max 0 b = b
Max a b = If (a <=? b) b a
- 3 types
- 6 classes
- 2 values
- Cpp
- MonoLocalBinds
- TemplateHaskell
- TemplateHaskellQuotes
- ScopedTypeVariables
- AllowAmbiguousTypes
- TypeFamilies
- GADTs
- GADTSyntax
- PolyKinds
- DataKinds
- TypeSynonymInstances
- FlexibleInstances
- ConstrainedClassMethods
- MultiParamTypeClasses
- MagicHash
- KindSignatures
- TypeOperators
- ExplicitNamespaces
- ExplicitForAll
- TypeApplications
- Packageghc-typelits-knownnat-0.7.12
- Exports11
- LanguageHaskell2010
- LicenceBSD-2-Clause
- SourceKnownNat.hs
Singleton natural number
1 declarationConstraint-level arithmetic classes
3 declarationsClass for arithmetic functions with one argument.
The Symbol f must correspond to the fully qualified name of the type-level operation. Use nameToSymbol to get the fully qualified TH Name as a Symbol
Class for arithmetic functions with two arguments.
The Symbol f must correspond to the fully qualified name of the type-level operation. Use nameToSymbol to get the fully qualified TH Name as a Symbol
Instances6KnownNat2
(KnownNat a, KnownNat b) => KnownNat2Defined in ghc-typelits-knownnat-0.7.12 · GHC.TypeLits.KnownNat"GHC.Internal.TypeNats.*"
a bKnownNat2 instance for GHC.TypeLits' *
(KnownNat a, KnownNat b) => KnownNat2Defined in ghc-typelits-knownnat-0.7.12 · GHC.TypeLits.KnownNat"GHC.Internal.TypeNats.+"
a bKnownNat2 instance for GHC.TypeLits' +
(KnownNat a, KnownNat b) => KnownNat2Defined in ghc-typelits-knownnat-0.7.12 · GHC.TypeLits.KnownNat"GHC.Internal.TypeNats.^"
a bKnownNat2 instance for GHC.TypeLits' ^
(KnownNat a, KnownNat b, (b <= a) ~ ()) => KnownNat2Defined in ghc-typelits-knownnat-0.7.12 · GHC.TypeLits.KnownNat"GHC.Internal.TypeNats.-"
a bKnownNat2 instance for GHC.TypeLits' -
(KnownNat x, KnownNat y, (Defined in ghc-typelits-knownnat-0.7.12 · GHC.TypeLits.KnownNat1
<= y) ~ ()) => KnownNat2"GHC.Internal.TypeNats.Div"
x y(KnownNat x, KnownNat y, (Defined in ghc-typelits-knownnat-0.7.12 · GHC.TypeLits.KnownNat1
<= y) ~ ()) => KnownNat2"GHC.Internal.TypeNats.Mod"
x y
Class for arithmetic functions with three arguments.
The Symbol f must correspond to the fully qualified name of the type-level operation. Use nameToSymbol to get the fully qualified TH Name as a Symbol
Singleton boolean
2 declarationsGet the Bool value associated with a type-level Bool
Use boolVal if you want to perform the standard boolean operations on the reified type-level Bool.
Use boolSing if you need a context in which the type-checker needs the type-level Bool to be either True or False
f :: forall proxy b r . KnownBool b => r
f = case boolSing @b of
SFalse -> -- context with b ~ False
STrue -> -- context with b ~ True
KnownBool
1 declarationConstraint-level boolean functions
Class for ternary functions with a Natural result.
The Symbol f must correspond to the fully qualified name of the type-level operation. Use nameToSymbol to get the fully qualified TH Name as a Symbol
Methods
natBoolSing3 :: SNatKn f
Instances1KnownNat2Bool
(KnownBool a, KnownNat b, KnownNat c) => KnownNat2BoolDefined in ghc-typelits-knownnat-0.7.12 · GHC.TypeLits.KnownNat"GHC.Internal.Data.Type.Bool.If"
a b c
Class for binary functions with a Boolean result.
The Symbol f must correspond to the fully qualified name of the type-level operation. Use nameToSymbol to get the fully qualified TH Name as a Symbol
Methods
boolNatSing2 :: SBoolKb f
Instances2KnownBoolNat2
(KnownNat a, KnownNat b) => KnownBoolNat2Defined in ghc-typelits-knownnat-0.7.12 · GHC.TypeLits.KnownNat"GHC.Internal.Data.Type.Ord.<=?"
a b(KnownNat a, KnownNat b) => KnownBoolNat2Defined in ghc-typelits-knownnat-0.7.12 · GHC.TypeLits.KnownNat"GHC.Internal.Data.Type.Ord.OrdCond"
a b