typenums-0.1.4: Type level numbers using existing Nat functionality
Copyright(c) 2018-2021 Iris Ward
LicenseBSD3
Maintaineraditu.venyhandottir@gmail.com
Stabilityexperimental
Safe HaskellSafe
LanguageHaskell2010

Data.TypeNums

Description

This module provides a unified interface for natural numbers, signed integers, and rationals at the type level, in a way fully compatible with existing code using type-level naturals.

Natural numbers are expressed as always, e.g. 5. Negative integers are written as Neg 3. Ratios are written as 3 :% 2.

There are some naming conflicts between this module and GHC.TypeLits, notably the comparison and arithmetic operators. This module reexports Nat, KnownNat, natVal and natVal' so you may import just this module and not GHC.TypeLits.

If you wish to use other functionality from GHC.TypeLits, this package also provides the module Data.TypeLits that includes (almost) full functionality from GHC.TypeLits, but with the conflicts resolving in this packages favour.

Synopsis

Type level numbers

Naturals

data Nat #

(Kind) This is the kind of type-level natural numbers.

Instances

Instances details
KnownNat n => KnownInt (n :: Nat) Source # 
Instance details

Defined in Data.TypeNums.Ints

Methods

intSing :: SInt n

class KnownNat (n :: Nat) #

This class gives the integer associated with a type-level natural. There are instances of the class for every concrete literal: 0, 1, 2, etc.

Since: base-4.7.0.0

Minimal complete definition

natSing

natVal :: forall (n :: Nat) proxy. KnownNat n => proxy n -> Integer #

Since: base-4.7.0.0

natVal' :: forall (n :: Nat). KnownNat n => Proxy# n -> Integer #

Since: base-4.8.0.0

data SomeNat #

This type represents unknown type-level natural numbers.

Since: base-4.10.0.0

Constructors

KnownNat n => SomeNat (Proxy n) 

Instances

Instances details
Eq SomeNat

Since: base-4.7.0.0

Instance details

Defined in GHC.TypeNats

Methods

(==) :: SomeNat -> SomeNat -> Bool #

(/=) :: SomeNat -> SomeNat -> Bool #

Ord SomeNat

Since: base-4.7.0.0

Instance details

Defined in GHC.TypeNats

Read SomeNat

Since: base-4.7.0.0

Instance details

Defined in GHC.TypeNats

Show SomeNat

Since: base-4.7.0.0

Instance details

Defined in GHC.TypeNats

someNatVal :: Integer -> Maybe SomeNat #

Convert an integer into an unknown type-level natural.

Since: base-4.7.0.0

Integers

data TInt Source #

(Kind) An integer that may be negative.

Constructors

Pos Nat 
Neg Nat 

Instances

Instances details
KnownNat n => KnownInt ('Pos n :: TInt) Source # 
Instance details

Defined in Data.TypeNums.Ints

Methods

intSing :: SInt ('Pos n)

KnownNat n => KnownInt ('Neg n :: TInt) Source # 
Instance details

Defined in Data.TypeNums.Ints

Methods

intSing :: SInt ('Neg n)

class KnownInt (n :: k) Source #

This class gives the (value-level) integer associated with a type-level integer. There are instances of this class for every concrete natural: 0, 1, 2, etc. There are also instances of this class for every negated natural, such as Neg 1.

Minimal complete definition

intSing

Instances

Instances details
KnownNat n => KnownInt (n :: Nat) Source # 
Instance details

Defined in Data.TypeNums.Ints

Methods

intSing :: SInt n

KnownNat n => KnownInt ('Pos n :: TInt) Source # 
Instance details

Defined in Data.TypeNums.Ints

Methods

intSing :: SInt ('Pos n)

KnownNat n => KnownInt ('Neg n :: TInt) Source # 
Instance details

Defined in Data.TypeNums.Ints

Methods

intSing :: SInt ('Neg n)

intVal :: forall n proxy. KnownInt n => proxy n -> Integer Source #

Get the value associated with a type-level integer

intVal' :: forall n. KnownInt n => Proxy# n -> Integer Source #

Get the value associated with a type-level integer. The difference between this function and intVal is that it takes a Proxy# parameter, which has zero runtime representation and so is entirely free.

data SomeInt Source #

This type represents unknown type-level integers.

Since: 0.1.1

Constructors

forall n.KnownInt n => SomeInt (Proxy n) 

Instances

Instances details
Eq SomeInt Source # 
Instance details

Defined in Data.TypeNums.Ints

Methods

(==) :: SomeInt -> SomeInt -> Bool #

(/=) :: SomeInt -> SomeInt -> Bool #

Ord SomeInt Source # 
Instance details

Defined in Data.TypeNums.Ints

Read SomeInt Source # 
Instance details

Defined in Data.TypeNums.Ints

Show SomeInt Source # 
Instance details

Defined in Data.TypeNums.Ints

someIntVal :: Integer -> SomeInt Source #

Convert an integer into an unknown type-level integer.

Since: 0.1.1

Rationals

data Rat Source #

Type constructor for a rational

Constructors

forall k. k :% Nat 

Instances

Instances details
(KnownInt n, KnownNat d, d /= 0) => KnownRat (n :% d :: Rat) Source # 
Instance details

Defined in Data.TypeNums.Rats

Methods

ratSing :: SRat (n :% d)

(TypeError ('Text "Denominator must not equal 0") :: Constraint) => KnownRat (n :% 0 :: Rat) Source # 
Instance details

Defined in Data.TypeNums.Rats

Methods

ratSing :: SRat (n :% 0)

class KnownRat r Source #

This class gives the (value-level) rational associated with a type-level rational. There are instances of this class for every combination of a concrete integer and concrete natural.

Minimal complete definition

ratSing

Instances

Instances details
KnownInt n => KnownRat (n :: k) Source # 
Instance details

Defined in Data.TypeNums.Rats

Methods

ratSing :: SRat n

(KnownInt n, KnownNat d, d /= 0) => KnownRat (n :% d :: Rat) Source # 
Instance details

Defined in Data.TypeNums.Rats

Methods

ratSing :: SRat (n :% d)

(TypeError ('Text "Denominator must not equal 0") :: Constraint) => KnownRat (n :% 0 :: Rat) Source # 
Instance details

Defined in Data.TypeNums.Rats

Methods

ratSing :: SRat (n :% 0)

ratVal :: forall proxy r. KnownRat r => proxy r -> Rational Source #

Get the value associated with a type-level rational

ratVal' :: forall r. KnownRat r => Proxy# r -> Rational Source #

Get the value associated with a type-level rational. The difference between this function and ratVal is that it takes a Proxy# parameter, which has zero runtime representation and so is entirely free.

data SomeRat Source #

This type represents unknown type-level integers.

Since: 0.1.1

Constructors

forall r.KnownRat r => SomeRat (Proxy r) 

Instances

Instances details
Eq SomeRat Source # 
Instance details

Defined in Data.TypeNums.Rats

Methods

(==) :: SomeRat -> SomeRat -> Bool #

(/=) :: SomeRat -> SomeRat -> Bool #

Ord SomeRat Source # 
Instance details

Defined in Data.TypeNums.Rats

Read SomeRat Source # 
Instance details

Defined in Data.TypeNums.Rats

Show SomeRat Source # 
Instance details

Defined in Data.TypeNums.Rats

someRatVal :: Rational -> SomeRat Source #

Convert a rational into an unknown type-level rational.

Since: 0.1.1

type family Simplify (x :: Rat) :: Rat where ... Source #

Reduce a type-level rational into its canonical form

Since: 0.1.4

Equations

Simplify ((x :: Nat) :% y) = Quot ('Pos x) (GCD x y) :% Quot y (GCD x y) 
Simplify ((x :: TInt) :% y) = Quot x (GCD x y) :% Quot y (GCD x y) 

Type level numerical operations

Comparisons

type family (a :: k1) ==? (b :: k2) :: Bool where ... infix 4 Source #

Boolean type-level equals. Useful for e.g. If (x ==? 0)

Equations

(a :: Rat) ==? (b :: Rat) = (==) (Simplify a) (Simplify b) 
(a :: Nat) ==? ('Pos a) = 'True 
('Pos a) ==? (a :: Nat) = 'True 
(a :: Nat) ==? (r :: Rat) = (a :% 1) ==? r 
(r :: Rat) ==? (a :: Nat) = r ==? (a :% 1) 
(a :: TInt) ==? (r :: Rat) = (a :% 1) ==? r 
(r :: Rat) ==? (a :: TInt) = r ==? (a :% 1) 
(a :: k) ==? (b :: k) = (==) a b 
_ ==? _ = 'False 

type (/=?) (a :: k1) (b :: k2) = Not (a ==? b) infix 4 Source #

Boolean type-level not-equals.

type (==) (a :: k1) (b :: k2) = (a ==? b) ~ 'True infix 4 Source #

Equality constraint, used as e.g. (x == 3) => _

type (/=) (a :: k1) (b :: k2) = (a ==? b) ~ 'False infix 4 Source #

Not-equal constraint

type family (a :: k1) <=? (b :: k2) :: Bool where ... infix 4 Source #

Boolean comparison of two type-level numbers

Equations

(a :: Nat) <=? (b :: Nat) = (<=?) a b 
('Pos a) <=? ('Pos b) = (<=?) a b 
('Neg _) <=? ('Pos _) = 'True 
('Pos 0) <=? ('Neg 0) = 'True 
('Pos _) <=? ('Neg _) = 'False 
('Pos a) <=? b = a <=? b 
a <=? ('Pos b) = a <=? b 
0 <=? ('Neg 0) = 'True 
(a :: Nat) <=? ('Neg _) = 'False 
('Neg a) <=? (b :: Nat) = 'True 
('Neg a) <=? ('Neg b) = (<=?) b a 
(n :% 0) <=? _ = TypeError ('Text "Denominator must not equal 0") 
_ <=? (n :% 0) = TypeError ('Text "Denominator must not equal 0") 
(n1 :% d1) <=? (n2 :% d2) = (n1 * d2) <=? (n2 * d1) 
a <=? (n :% d) = (a * d) <=? n 
(n :% d) <=? b = n <=? (b * d) 
_ <=? _ = TypeError ('Text "Incomparable") 

type (<=) (a :: k1) (b :: k2) = (a <=? b) ~ 'True infix 4 Source #

type (<) (a :: k1) (b :: k2) = (b <=? a) ~ 'False infix 4 Source #

type (>=) (a :: k1) (b :: k2) = (b <=? a) ~ 'True infix 4 Source #

type (>) (a :: k1) (b :: k2) = (a <=? b) ~ 'False infix 4 Source #

Arithmetic

Unary Operations

type family Abs (x :: k) :: k where ... Source #

The absolute value of a type-level number

Since: 0.1.4

Equations

Abs (x :: Nat) = x 
Abs ('Pos x) = 'Pos x 
Abs ('Neg x) = 'Pos x 
Abs (x :% y) = Simplify (Abs x :% y) 

type family Negate (x :: k) :: NegK k where ... Source #

The result of negating a TInt

Since: 0.1.4

Equations

Negate (x :: Nat) = Negate ('Pos x) 
Negate ('Pos 0) = 'Pos 0 
Negate ('Neg 0) = 'Pos 0 
Negate ('Pos x) = 'Neg x 
Negate ('Neg x) = 'Pos x 
Negate (x :% y) = Negate x :% y 

type family Recip (x :: k) :: Rat where ... Source #

The reciprocal of a type-level number

Since: 0.1.4

Equations

Recip (x :: Nat) = 'Pos 1 :% x 
Recip ('Pos x) = 'Pos 1 :% x 
Recip ('Neg x) = 'Neg 1 :% x 
Recip ('Pos x :% y) = 'Pos y :% x 
Recip ('Neg x :% y) = 'Neg y :% x 
Recip ((x :: Nat) :% y) = 'Pos y :% x 

type family Floor (x :: k) :: TInt where ... Source #

Round a type-level number towards negative infinity

Since: 0.1.4

Equations

Floor (x :: Nat) = 'Pos x 
Floor (x :: TInt) = x 
Floor (x :% 0) = TypeError ('Text "The denominator must not be 0") 
Floor ((x :: Nat) :% y) = 'Pos (Div x y) 
Floor ((x :: TInt) :% y) = Div x y 

type family Ceiling (x :: k) :: TInt where ... Source #

Round a type-level number towards positive infinity

Since: 0.1.4

Equations

Ceiling (x :: Nat) = 'Pos x 
Ceiling (x :: TInt) = x 
Ceiling (x :% 0) = TypeError ('Text "The denominator must not be 0") 
Ceiling (x :% y) = Add 1 (Floor (Sub x 1 :% y)) 

type family Truncate (x :: k) :: TInt where ... Source #

Round a type-level number towards zero

Since: 0.1.4

Equations

Truncate (x :: Nat) = 'Pos x 
Truncate (x :: TInt) = x 
Truncate (x :% 0) = TypeError ('Text "The denominator must not be 0") 
Truncate ((x :: Nat) :% y) = 'Pos (Quot x y) 
Truncate ((x :: TInt) :% y) = Quot x y 

Binary Operations

type (+) a b = Add a b infixl 6 Source #

The sum of two type-level numbers

type (-) a b = Sub a b infixl 6 Source #

The difference of two type-level numbers

For the difference of two naturals a and b, a-b is also a natural, so only exists for a >= b.

type * a b = Mul a b infixl 7 Source #

The product of two type-level numbers.

Due to changes in GHC 8.6, using this operator infix and unqualified requires the NoStarIsType language extension to be active. See the GHC 8.6.x migration guide for details: https://ghc.haskell.org/trac/ghc/wiki/Migration/8.6

type (/) a b = RatDiv a b infixl 7 Source #

The ratio of two type-level numbers

type (^) a b = Exp a b infixr 8 Source #

A type-level number raised to an integer power. For Nat powers, the result kind is the same as the base. For TInt powers, the result kind is Rat.

Since: 0.1.4

type family DivMod (x :: k) (y :: Nat) :: (IntDivK k, IntDivK k) where ... Source #

The quotient and remainder of a type-level integer and a natural number. For a negative dividend, the remainder part is positive such that x = q*y + r @since 0.1.4

Equations

DivMod _ 0 = TypeError ('Text "Divisor must not be 0") 
DivMod (x :: Nat) y = UnPos (DivModAux ('Pos x) y ('Pos 0)) 
DivMod ('Pos x) y = DivModAux ('Pos x) y ('Pos 0) 
DivMod ('Neg x) y = DivModNegFixup (DivModAux ('Pos x) y ('Pos 0)) y 

type family QuotRem (x :: k) (y :: Nat) :: (IntDivK k, IntDivK k) where ... Source #

The quotient and remainder of a type-level integer and a natural number. For a negative dividend, the remainder part is negative such that x = q*y + r @since 0.1.4

Equations

QuotRem ('Neg x) y = QuotRemFixup (DivMod ('Neg x) y) y 
QuotRem x y = DivMod x y 

type family Div (x :: k) (y :: Nat) :: IntDivK k where ... infixl 7 Source #

The quotient of a type-level integer and a natural number.

Since: 0.1.4

Equations

Div x y = Fst (DivMod x y) 

type family Mod (x :: k) (y :: Nat) :: IntDivK k where ... infixl 7 Source #

The remainder of a type-level integer and a natural number For a negative number, behaves similarly to mod. @since 0.1.4

Equations

Mod x y = Snd (DivMod x y) 

type family Quot (x :: k) (y :: Nat) :: IntDivK k where ... infixl 7 Source #

The integer part of the result of dividing an integer by a natural number

Since: 0.1.4

Equations

Quot x y = Fst (QuotRem x y) 

type family Rem (x :: k) (y :: Nat) :: IntDivK k where ... infixl 7 Source #

The remainder of the result of dividing an integer by a natural number

Since: 0.1.4

Equations

Rem x y = Snd (QuotRem x y) 

type family GCD (x :: k1) (y :: k2) :: Nat where ... Source #

The greatest common divisor of two type-level integers

Since: 0.1.4

Equations

GCD (x :: Nat) (y :: Nat) = GCDAux x y 
GCD (x :: Nat) (y :: TInt) = GCDAux x (UnPos (Abs y)) 
GCD (x :: TInt) (y :: Nat) = GCDAux (UnPos (Abs x)) y 
GCD (x :: TInt) (y :: TInt) = GCDAux (UnPos (Abs x)) (UnPos (Abs y)) 

type family IntLog (n :: Nat) (x :: k) :: TInt where ... Source #

The floor of the logarithm of a type-level number NB. unlike Log2, Log n 0 here is a type error.

Since: 0.1.4

Equations

IntLog 0 _ = TypeError ('Text "Invalid IntLog base: 0") 
IntLog 1 _ = TypeError ('Text "Invalid IntLog base: 1") 
IntLog _ 0 = TypeError ('Text "IntLog n 0 is infinite") 
IntLog _ ('Pos 0) = TypeError ('Text "IntLog n 0 is infinite") 
IntLog _ ('Neg 0) = TypeError ('Text "IntLog n 0 is infinite") 
IntLog _ (0 :% _) = TypeError ('Text "IntLog n 0 is infinite") 
IntLog _ (_ :% 0) = TypeError ('Text "IntLog parameter has zero denominator") 
IntLog _ ('Neg _) = TypeError ('Text "IntLog of a negative does not exist") 
IntLog n (x :: Nat) = IntLog n ('Pos x) 
IntLog n ('Pos x) = IntLogAux n ('Pos x) 
IntLog n (x :: Rat) = If (Floor x == 'Pos 0) (NegLogFudge n x (Negate (IntLogAux n (Floor (Recip x))))) (IntLog n (Floor x)) 

type Log2 x = IntLog 2 x Source #

The floor of the logarithm base 2 of a type-level number. Note that unlike Log2, this errors on Log2 0.

Since: 0.1.4