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
- 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 might also be 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. Notwithstanding this, for
ergonomic reasons, all of the functions exported by this module take
Prelude Rational
s as input and produce Prelude Rational
s as outputs.
Internally, however, the beforementioned checks are always performed, and
fail with throw
if necessary. If you want to be sure those error
s
never happen, just filter your Prelude Rational
s with fromPrelude
. In
practice, it's very unlikely that you will be affected by this unless if
you are unsafelly constructing Prelude Rational
s.
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 | |
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 | |
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
fmap
toPrelude
.fromPrelude
==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 #
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 # | |
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 # |
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 #
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 #
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 #
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 Prelude 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.