Prim.hs (1998B)
1 module Naturals.Speano.Prim ( 2 SpeanoSig (..), 3 Speano (..), 4 speanoShow, 5 speano, 6 speanoInd, 7 speanoRec, 8 speanoFold, 9 speanoPred, 10 speanoAdd, 11 ) where 12 13 import Data.Coerce 14 import Data.Functor.Const 15 16 import Naturals.Natural 17 import Naturals.Peano 18 19 -- | The "signature" of singleton (@Peano@-indexed) natural numbers: 20 -- @SpeanoSig@ is to @Speano@ as @Maybe@ is to @Peano@. 21 data SpeanoSig f n where 22 ZeroOp :: SpeanoSig f Z 23 SuccOp :: f n -> SpeanoSig f (S n) 24 25 -- | Singleton (@Peano@-indexed) unary natural numbers. 26 -- 27 -- @Speano@ is implemented as a GADT, and hence is inefficient. 28 -- See @Snat@ and @Snatural@ for efficient alternatives. 29 data Speano n where 30 Zero :: Speano Z 31 Succ :: Speano n -> Speano (S n) 32 33 deriving instance Eq (Speano n) 34 35 instance Show (Speano n) where 36 show = show . toNatural 37 38 -- | A variant of @show \@(Speano n)@ that uses unary notation instead of decimal. 39 speanoShow :: Speano n -> String 40 speanoShow Zero = "Z" 41 speanoShow (Succ n) = 'S' : speanoShow n 42 43 instance ToNatural (Speano n) where 44 toNatural Zero = 0 45 toNatural (Succ n) = succ (toNatural n) 46 47 -- | The (nonrecursive) eliminator for @Speano@ (equivalent to a case 48 -- expression). 49 speano :: ((n ~ Z) => a) -> (forall m. (n ~ S m) => Speano m -> a) -> Speano n -> a 50 speano z _ Zero = z 51 speano _ s (Succ m) = s m 52 53 -- | Induction for @Speano@. 54 speanoInd :: f Z -> (forall m. Speano m -> f m -> f (S m)) -> Speano n -> f n 55 speanoInd z _ Zero = z 56 speanoInd z s (Succ m) = s m (speanoInd z s m) 57 58 -- | The (nondependent) recursor for @Speano@. 59 speanoRec :: forall a n. a -> (forall m. Speano m -> a -> a) -> Speano n -> a 60 speanoRec = coerce $ speanoInd @(Const a) @n 61 62 -- | The catamorphism for @Speano@. 63 speanoFold :: a -> (a -> a) -> Speano n -> a 64 speanoFold z s = speanoRec z (const s) 65 66 speanoPred :: Speano (S n) -> Speano n 67 speanoPred (Succ n) = n 68 69 speanoAdd :: Speano m -> Speano n -> Speano (Add m n) 70 speanoAdd Zero n = n 71 speanoAdd (Succ m) n = Succ (speanoAdd m n)