module Combinatorics.Battleship.Size where
data Zero = Zero
data Succ n = Succ n
type N0 = Zero
type N1 = Succ N0 ; type P1 w = Succ w
type N2 = Succ N1 ; type P2 w = Succ (P1 w)
type N3 = Succ N2 ; type P3 w = Succ (P2 w)
type N4 = Succ N3 ; type P4 w = Succ (P3 w)
type N5 = Succ N4 ; type P5 w = Succ (P4 w)
type N6 = Succ N5 ; type P6 w = Succ (P5 w)
type N7 = Succ N6 ; type P7 w = Succ (P6 w)
type N8 = Succ N7 ; type P8 w = Succ (P7 w)
type N9 = Succ N8 ; type P9 w = Succ (P8 w)
type N10 = Succ N9 ; type P10 w = Succ (P9 w)
type N11 = Succ N10 ; type P11 w = Succ (P10 w)
type N12 = Succ N11 ; type P12 w = Succ (P11 w)
n0 :: Size N0; n0 = size
n1 :: Size N1; n1 = size
n2 :: Size N2; n2 = size
n3 :: Size N3; n3 = size
n4 :: Size N4; n4 = size
n5 :: Size N5; n5 = size
n6 :: Size N6; n6 = size
n7 :: Size N7; n7 = size
n8 :: Size N8; n8 = size
n9 :: Size N9; n9 = size
n10 :: Size N10; n10 = size
newtype Size n = Size {getSize :: Int}
incSize :: Size n -> Size (Succ n)
incSize (Size n) = Size (n+1)
class Nat n where switch :: f Zero -> (forall m. Nat m => f (Succ m)) -> f n
instance Nat Zero where switch f _ = f
instance Nat n => Nat (Succ n) where switch _ f = f
size :: Nat n => Size n
size = switch (Size 0) (incSize size)
reifyInt :: Int -> (forall n. Nat n => Size n -> a) -> a
reifyInt n f =
if n==0
then f n0
else reifyInt (n1) $ f . incSize