Safe Haskell | Safe-Inferred |
---|---|
Language | GHC2021 |
This module provides a type-level representation for term-level
Rational
s. 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 Natural
s
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 /
dNormalize
s 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
(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 Num
erator and denominator have no common factors.
Only Normalize
d Rational
s can be reliably constrained for equality
using ~
.
All of the functions in the KindRational module accept both
Normalize
d and non-Normalize
d inputs, but they always produce
Normalize
d 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 Normalize
d.
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.
shows
0 (rationalVal
(Proxy
@(1/
2))) "z" == "1 % 2z"showsPrecTypeLit
0 (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.
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 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
.
forall n.KnownRational n => SomeRational (Proxy n) |
Instances
Read SomeRational Source # | |
Defined in KindRational readsPrec :: Int -> ReadS SomeRational # readList :: ReadS [SomeRational] # | |
Show SomeRational Source # | |
Defined in KindRational 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 (==) :: SomeRational -> SomeRational -> Bool # (/=) :: SomeRational -> SomeRational -> Bool # | |
Ord SomeRational Source # | |
Defined in KindRational 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 ::KnownRational
r =>SRational
r
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 Normalize
d.
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
.
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
rRational
s 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 Rational
s, 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 Rational
s 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.