packages feed

witness-0.7: src/Data/PeanoNat.hs

module Data.PeanoNat where

import GHC.TypeNats
import Import

-- | Inductive natural numbers.
data PeanoNat
    = Zero
    | Succ PeanoNat

addPeanoNat :: PeanoNat -> PeanoNat -> PeanoNat
addPeanoNat Zero b = b
addPeanoNat (Succ a) b = Succ $ addPeanoNat a b

type Add :: PeanoNat -> PeanoNat -> PeanoNat
type family Add a b where
    Add 'Zero b = b
    Add ('Succ a) b = 'Succ (Add a b)

-- | subtractFromPeanoNat a b = b - a
subtractFromPeanoNat :: PeanoNat -> PeanoNat -> Maybe PeanoNat
subtractFromPeanoNat Zero b = Just b
subtractFromPeanoNat (Succ a) (Succ b) = subtractFromPeanoNat a b
subtractFromPeanoNat (Succ _) Zero = Nothing

multiplyPeanoNat :: PeanoNat -> PeanoNat -> PeanoNat
multiplyPeanoNat Zero _ = Zero
multiplyPeanoNat (Succ a) b = addPeanoNat (multiplyPeanoNat a b) b

peanoToNatural :: PeanoNat -> Natural
peanoToNatural Zero = 0
peanoToNatural (Succ n) = succ $ peanoToNatural n

naturalToPeano :: Natural -> PeanoNat
naturalToPeano 0 = Zero
naturalToPeano n = Succ $ naturalToPeano $ pred n

type PeanoToNatural :: PeanoNat -> Nat
type family PeanoToNatural pn where
    PeanoToNatural 'Zero = 0
    PeanoToNatural ('Succ pn) = PeanoToNatural pn + 1

type ListLength :: forall k. [k] -> PeanoNat
type family ListLength l where
    ListLength '[] = 'Zero
    ListLength (_ ': aa) = 'Succ (ListLength aa)