{-# language DataKinds #-}
{-# language ExplicitForAll #-}
{-# language KindSignatures #-}
{-# language MagicHash #-}
{-# language RankNTypes #-}
{-# language ScopedTypeVariables #-}
{-# language TypeOperators #-}
module Arithmetic.Nat
(
plus
, monus
, succ
, testEqual
, testLessThan
, testLessThanEqual
, testZero
, (=?)
, (<?)
, (<=?)
, zero
, one
, two
, three
, constant
, demote
, with
) where
import Prelude hiding (succ)
import Arithmetic.Types
import Arithmetic.Unsafe ((:=:)(Eq), type (<=)(Lte))
import Arithmetic.Unsafe (Nat(Nat),type (<)(Lt))
import GHC.Exts (Proxy#,proxy#)
import GHC.TypeNats (type (+),KnownNat,natVal')
(<?) :: Nat a -> Nat b -> Maybe (a < b)
(<?) = testLessThan
(<=?) :: Nat a -> Nat b -> Maybe (a <= b)
(<=?) = testLessThanEqual
(=?) :: Nat a -> Nat b -> Maybe (a :=: b)
(=?) = testEqual
testLessThan :: Nat a -> Nat b -> Maybe (a < b)
testLessThan (Nat x) (Nat y) = if x < y
then Just Lt
else Nothing
testLessThanEqual :: Nat a -> Nat b -> Maybe (a <= b)
testLessThanEqual (Nat x) (Nat y) = if x <= y
then Just Lte
else Nothing
testEqual :: Nat a -> Nat b -> Maybe (a :=: b)
testEqual (Nat x) (Nat y) = if x == y
then Just Eq
else Nothing
testZero :: Nat a -> Either (0 :=: a) (0 < a)
testZero (Nat x) = case x of
0 -> Left Eq
_ -> Right Lt
plus :: Nat a -> Nat b -> Nat (a + b)
plus (Nat x) (Nat y) = Nat (x + y)
succ :: Nat a -> Nat (a + 1)
succ n = plus n one
monus :: Nat a -> Nat b -> Maybe (Difference a b)
{-# inline monus #-}
monus (Nat a) (Nat b) = let c = a - b in if c >= 0
then Just (Difference (Nat c) Eq)
else Nothing
zero :: Nat 0
zero = Nat 0
one :: Nat 1
one = Nat 1
two :: Nat 2
two = Nat 2
three :: Nat 3
three = Nat 3
constant :: forall n. KnownNat n => Nat n
constant = Nat (fromIntegral (natVal' (proxy# :: Proxy# n)))
demote :: Nat n -> Int
demote (Nat n) = n
with :: Int -> (forall n. Nat n -> a) -> a
with i f = f (Nat i)