| Safe Haskell | Safe-Inferred |
|---|---|
| Language | GHC2021 |
KindRational
Description
This module provides a type-level representation for term-level
Rationals. This type-level representation is also named Rational,
So import this module qualified to avoid name conflicts.
import KindRational qualified as KR
The implementation details are the same as the ones for type-level Naturals
in GHC.TypeNats as of base-4.18, and it will continue to evolve together
with base, trying to follow its core API as much as possible until the day
base provides its own type-level rationals, making this module redundant.
Synopsis
- data Rational
- type (%) (n :: Integer) (d :: Natural) = n :% d :: Rational
- type family n / d :: Rational where ...
- type family Normalize (r :: Rational) :: Rational where ...
- type Num (r :: Rational) = Num_ (Normalize r) :: Integer
- type Den (r :: Rational) = Den_ (Normalize r) :: Natural
- rational :: (Integral num, Integral den) => num -> den -> Maybe Rational
- fromPrelude :: Rational -> Maybe Rational
- toPrelude :: Rational -> Rational
- showsPrecTypeLit :: Int -> Rational -> ShowS
- class KnownRational (r :: Rational) where
- rationalSing :: SRational r
- rationalVal :: forall r proxy. KnownRational r => proxy r -> Rational
- data SomeRational = forall n.KnownRational n => SomeRational (Proxy n)
- someRationalVal :: Rational -> SomeRational
- sameRational :: forall a b proxy1 proxy2. (KnownRational a, KnownRational b) => proxy1 a -> proxy2 b -> Maybe (a :~: b)
- data SRational (r :: Rational)
- pattern SRational :: forall r. () => KnownRational r => SRational r
- fromSRational :: SRational r -> Rational
- withSomeSRational :: forall rep (a :: TYPE rep). Rational -> (forall r. SRational r -> a) -> a
- withKnownRational :: forall r rep (a :: TYPE rep). SRational r -> (KnownRational r => a) -> a
- type (+) (a :: Rational) (b :: Rational) = Add_ (Normalize a) (Normalize b) :: Rational
- type * (a :: Rational) (b :: Rational) = Mul_ (Normalize a) (Normalize b) :: Rational
- type (-) (a :: Rational) (b :: Rational) = a + Negate b :: Rational
- type family Negate (r :: Rational) :: Rational where ...
- type Sign (r :: Rational) = Sign (Num r) :: Integer
- type Abs (r :: Rational) = Normalize (P (Abs (Num_ r)) % Den_ r) :: Rational
- type Recip (a :: Rational) = Recip_ (Normalize a) :: Rational
- type Div (r :: Round) (a :: Rational) = Div_ r (Normalize a) :: Integer
- div :: Round -> Rational -> Integer
- type Rem (r :: Round) (a :: Rational) = Snd (DivRem r a) :: Rational
- rem :: Round -> Rational -> Rational
- type DivRem (r :: Round) (a :: Rational) = DivRem_ r (Normalize a) :: (Integer, Rational)
- divRem :: Round -> Rational -> (Integer, Rational)
- data Round
- class (KnownRational r, Terminates r ~ True) => Terminating (r :: Rational)
- withTerminating :: forall r a. KnownRational r => (Terminating r => a) -> Maybe a
- type Terminates (r :: Rational) = Terminates_ (Den r) :: Bool
- terminates :: Rational -> Bool
- type CmpRational (a :: Rational) (b :: Rational) = CmpRational_ (Normalize a) (Normalize b) :: Ordering
- cmpRational :: forall a b proxy1 proxy2. (KnownRational a, KnownRational b) => proxy1 a -> proxy2 b -> OrderingI a b
- eqRationalRep :: Rational -> Rational -> Bool
- type (==?) (a :: k) (b :: k) = OrdCond (Compare a b) 'False 'True 'False
- type (==) (a :: k) (b :: k) = (a ==? b) ~ 'True
- type (/=?) (a :: k) (b :: k) = OrdCond (Compare a b) 'True 'False 'True
- type (/=) (a :: k) (b :: k) = (a /=? b) ~ 'True
Rational kind
Type-level version of Rational. Use / to construct one, use % to
pattern-match on it.
Rational is mostly used as a kind, with its types constructed
using /. However, it is also used as type, with its terms
constructed using rational or fromPrelude. One reason why you may want a
Rational at the term-level is so that you embed it in larger data-types
(for example, this Rational embeds the Integer similarly offered by
the KindInteger module). But perhaps more importantly, this Rational
offers better safety than the Rational from Prelude, since it's not
possible to construct one with a zero denominator, or so large that
operating with it would exhaust system resources. Additionally,
a KindRational's Rational can fully represent the internal structure
of a type-level Rational. For these reasons, functions like
fromSRational and withSomeSRational deal with it, rather than with
Prelude's Rational.
Instances
| Read Rational Source # | |
| Show Rational Source # | |
| Eq Rational Source # | Arithmethic equality. That is, \(\frac{1}{2} == \frac{2}{4}\). |
| Ord Rational Source # | |
Defined in KindRational | |
| SingKind Rational Source # |
|
| SDecide Rational Source # | Note that this checks for type equality, not arithmetic equality.
That is, |
| TestCoercion SRational Source # | Note that this checks for type equality, not arithmetic equality.
That is, |
Defined in KindRational | |
| TestEquality SRational Source # | Note that this checks for type equality, not arithmetic equality.
That is, |
Defined in KindRational | |
| KnownRational r => SingI (r :: Rational) Source # | |
Defined in KindRational | |
| type Demote Rational Source # | |
Defined in KindRational | |
| type Sing Source # | |
Defined in KindRational | |
| type Compare (a :: Rational) (b :: Rational) Source # | Data.Type.Ord support for type-level |
Defined in KindRational | |
type family n / d :: Rational where ... infixl 7 Source #
n constructs and /dNormalizes a type-level Rational
with numerator n and denominator d.
This type-family accepts any combination of Natural, Integer and
Rational as input.
(/) ::Natural->Natural->Rational(/) ::Natural->Integer->Rational(/) ::Natural->Rational->Rational(/) ::Integer->Natural->Rational(/) ::Integer->Integer->Rational(/) ::Integer->Rational->Rational(/) ::Rational->Natural->Rational(/) ::Rational->Integer->Rational(/) ::Rational->Rational->Rational
It's not possible to pattern-match on n. Instead, you must
pattern match on /dx, where %yx.%y ~ n/d
Equations
| (n :: Natural) / (d :: Natural) = Normalize (P n % d) | |
| (n :: Natural) / (P d :: Integer) = Normalize (P n % d) | |
| (n :: Natural) / (N d :: Integer) = Normalize (N n % d) | |
| (n :: Natural) / (d :: Rational) = (P n % 1) * Recip d | |
| (i :: Integer) / (d :: Natural) = Normalize (i % d) | |
| (P n :: Integer) / (P d :: Integer) = Normalize (P n % d) | |
| (N n :: Integer) / (N d :: Integer) = Normalize (P n % d) | |
| (P n :: Integer) / (N d :: Integer) = Normalize (N n % d) | |
| (N n :: Integer) / (P d :: Integer) = Normalize (N n % d) | |
| (n :: Integer) / (d :: Rational) = (n % 1) * Recip d | |
| (n :: Rational) / (d :: Natural) = n * Recip (P d % 1) | |
| (n :: Rational) / (d :: Integer) = n * Recip (d % 1) | |
| (n :: Rational) / (d :: Rational) = n * Recip d |
type family Normalize (r :: Rational) :: Rational where ... Source #
Normalize a type-level Rational so that a 0 denominator fails to
type-check, and that the Numerator and denominator have no common factors.
Only Normalized Rationals can be reliably constrained for equality
using ~.
All of the functions in the KindRational module accept both
Normalized and non-Normalized inputs, but they always produce
Normalized output.
rational :: (Integral num, Integral den) => num -> den -> Maybe Rational Source #
Make a term-level KindRational Rational number, provided that
the numerator is not 0, and that its numerator and denominator are
not so large that they would exhaust system resources. The Rational
is Normalized.
fromPrelude :: Rational -> Maybe Rational Source #
Try to obtain a term-level KindRational Rational from a term-level
Prelude Rational. This can fail if the Prelude Rational is
infinite, or if it is so big that it would exhaust system resources.
fromPrelude.toPrelude==Just
toPrelude :: Rational -> Rational Source #
Convert a term-level KindRational Rational into a Normalized
term-level Prelude Rational.
fromPrelude.toPrelude==Just
showsPrecTypeLit :: Int -> Rational -> ShowS Source #
Shows the Rational as it appears literally at the type-level.
This is remerent from normal show for Rational, which shows
the term-level value.
shows0 (rationalVal(Proxy@(1/2))) "z" == "1 % 2z"showsPrecTypeLit0 (rationalVal(Proxy@(1/2))) "z" == "P 1 % 2z"
Types ⇔ Terms
class KnownRational (r :: Rational) where Source #
This class gives the rational associated with a type-level rational. There are instances of the class for every rational.
Methods
rationalSing :: SRational r Source #
Instances
| (Normalize r ~ (n % d), KnownInteger (Num_ r), KnownNat (Den_ r)) => KnownRational r Source # | This instance checks that |
Defined in KindRational Methods rationalSing :: SRational r Source # | |
rationalVal :: forall r proxy. KnownRational r => proxy r -> Rational Source #
Term-level KindRational Rational representation of the type-level
Rational r.
data SomeRational Source #
This type represents unknown type-level Rational.
Constructors
| forall n.KnownRational n => SomeRational (Proxy n) |
Instances
| Read SomeRational Source # | |
Defined in KindRational Methods readsPrec :: Int -> ReadS SomeRational # readList :: ReadS [SomeRational] # | |
| Show SomeRational Source # | |
Defined in KindRational Methods showsPrec :: Int -> SomeRational -> ShowS # show :: SomeRational -> String # showList :: [SomeRational] -> ShowS # | |
| Eq SomeRational Source # | Arithmethic equality. That is, \(\frac{1}{2} == \frac{2}{4}\). |
Defined in KindRational | |
| Ord SomeRational Source # | |
Defined in KindRational Methods compare :: SomeRational -> SomeRational -> Ordering # (<) :: SomeRational -> SomeRational -> Bool # (<=) :: SomeRational -> SomeRational -> Bool # (>) :: SomeRational -> SomeRational -> Bool # (>=) :: SomeRational -> SomeRational -> Bool # max :: SomeRational -> SomeRational -> SomeRational # min :: SomeRational -> SomeRational -> SomeRational # | |
someRationalVal :: Rational -> SomeRational Source #
Convert a term-level KindRational Rational into an unknown
type-level Rational.
sameRational :: forall a b proxy1 proxy2. (KnownRational a, KnownRational b) => proxy1 a -> proxy2 b -> Maybe (a :~: b) Source #
Singletons
data SRational (r :: Rational) Source #
Singleton type for a type-level Rational r.
Instances
| TestCoercion SRational Source # | Note that this checks for type equality, not arithmetic equality.
That is, |
Defined in KindRational | |
| TestEquality SRational Source # | Note that this checks for type equality, not arithmetic equality.
That is, |
Defined in KindRational | |
| Show (SRational r) Source # | |
pattern SRational :: forall r. () => KnownRational r => SRational r Source #
A explicitly bidirectional pattern synonym relating an SRational to a
KnownRational constraint.
As an expression: Constructs an explicit value from an
implicit SRational r constraint:KnownRational r
SRational@r ::KnownRationalr =>SRationalr
As a pattern: Matches on an explicit value bringing
an implicit SRational r constraint into scope:KnownRational r
f :: SRational r -> ..
f SRational = {- SRational r in scope -}
fromSRational :: SRational r -> Rational Source #
Return the term-level KindRational Rational number corresponding
to r in a value. This SRational rRational is not Normalized.
withSomeSRational :: forall rep (a :: TYPE rep). Rational -> (forall r. SRational r -> a) -> a Source #
Convert a KindRational Rational number into an value,
where SRational nn is a fresh type-level Rational.
withKnownRational :: forall r rep (a :: TYPE rep). SRational r -> (KnownRational r => a) -> a Source #
Convert an explicit value into an implicit
SRational r constraint.KnownRational r
Arithmethic
type (+) (a :: Rational) (b :: Rational) = Add_ (Normalize a) (Normalize b) :: Rational infixl 6 Source #
type * (a :: Rational) (b :: Rational) = Mul_ (Normalize a) (Normalize b) :: Rational infixl 7 Source #
div :: Round -> Rational -> Integer Source #
Term-level version of Div.
Takes a KindInteger Rational as input, returns a Prelude
Integer.
rem :: Round -> Rational -> Rational Source #
Term-level version of Rem.
Takes a KindInteger Rational as input, returns a KindInteger Rational.
Constructors
| RoundUp | Round up towards positive infinity. |
| RoundDown | Round down towards negative infinity. Also known as Prelude's
|
| RoundZero | Round towards zero. Also known as Prelude's |
| RoundAway | Round away from zero. |
| RoundHalfUp | Round towards the closest integer. If halfway between two integers, round up towards positive infinity. |
| RoundHalfDown | Round towards the closest integer. If halfway between two integers, round down towards negative infinity. |
| RoundHalfZero | Round towards the closest integer. If halfway between two integers, round towards zero. |
| RoundHalfAway | Round towards the closest integer. If halfway between two integers, round away from zero. |
| RoundHalfEven | Round towards the closest integer. If halfway between two integers,
round towards the closest even integer. Also known as Prelude's
|
| RoundHalfOdd | Round towards the closest integer. If halfway between two integers, round towards the closest odd integer. |
Decimals
class (KnownRational r, Terminates r ~ True) => Terminating (r :: Rational) Source #
Constraint version of . Satisfied by all type-level
Terminates rRationals that can be represented as a finite decimal number.
Instances
| (KnownRational r, Terminates r ~ 'True, If (Terminates r) () (TypeError ((('Text "\8216" ':<>: 'ShowType r) ':<>: 'Text "\8217 is not a terminating ") ':<>: 'ShowType Rational) :: Constraint)) => Terminating r Source # | |
Defined in KindRational | |
withTerminating :: forall r a. KnownRational r => (Terminating r => a) -> Maybe a Source #
type Terminates (r :: Rational) = Terminates_ (Den r) :: Bool Source #
Whether the type-level Rational terminates. That is, whether
it can be fully represented as a finite decimal number.
terminates :: Rational -> Bool Source #
Term-level version of the Terminates function.
Takes a KindRational Rational as input.
Comparisons
type CmpRational (a :: Rational) (b :: Rational) = CmpRational_ (Normalize a) (Normalize b) :: Ordering Source #
Comparison of type-level Rationals, as a function.
cmpRational :: forall a b proxy1 proxy2. (KnownRational a, KnownRational b) => proxy1 a -> proxy2 b -> OrderingI a b Source #
Like sameRational, but if the type-level Rationals aren't equal, this
additionally provides proof of LT or GT.
Extra
This stuff should be exported by the Data.Type.Ord module.
type (==?) (a :: k) (b :: k) = OrdCond (Compare a b) 'False 'True 'False infixr 4 #
This should be exported by Data.Type.Ord.