--

type Quad a = (a,a,a,a)

data Quadtree a = Z a | S (Quad (Quadtree a))

mapQ :: (a -> b) -> Quadtree a -> Quadtree b
mapQ f (Z x) = Z(f x)
mapQ f (S(w,x,y,z)) = S(mapQ f w,mapQ f x,mapQ f y,mapQ f z)

--- Now consider

data QT2 a = Z2 a
           | S2 (QT2(Quad a))

-- S2 :: QT2 (Quad a) -> QT2 a
-- S2 :: QT2 (a,a,a,a) -> QT2 a

-- Note how things of type Quadtree can have any shape
ex1 = S(Z 2,Z 5, Z 0,S(Z 1,Z 4,Z 7,Z 1))


-- Including square things
ex2 = S(S(Z  1, Z  2, Z  3, Z  4)
       ,S(Z  5, Z  6, Z  7, Z  8)
       ,S(Z  9, Z 10, Z 11, Z 12)
       ,S(Z 13, Z 14, Z 15, Z 16))

-- But things of type QT2 can only be square       
ex3 = S2(S2(Z2(( 1, 2, 3, 4),
               ( 5, 6, 7, 8),
               ( 9,10,11,12),
               (13,14,15,16))))

ex2a = mapQ (+1) ex2

-- can we write a mapQ2 ?
-- only if we give an explicit type signature

mapQ2 :: (a -> b) -> QT2 a -> QT2 b
mapQ2 f (Z2 x) = Z2(f x)
mapQ2 f (S2 z) = S2(mapQ2 (mapQuad f) z)
  where mapQuad f (a,b,c,d) = (f a, f b, f c, f d)

-- How could you make a 3 by 3 square matrix?

type Tri a = (a,a,a)

-- Tri Trees
data TT a = Z3 a
          | S3 (TT(Tri a))
          
ex4 = S3 (S3 (Z3 ((1,2,3),
                  (4,5,6),
                  (7,8,9))))
  
-- Now what about square matrices for sizes that are not powers of 2?  

-- Fast exponentiation

power b n = fast 1 b n

fast acc b n 
  | n==0   = acc
  | even n = fast acc (b*b) (half n)
  | odd n  = fast (acc*b) (b*b) (half n)

half :: Int -> Int
half x = div x 2

-- lifted to the type level we get vectors of arbitrary size

type Vector a = Vector_ () a
data Vector_ v w 
  = Zero v
  | Even (Vector_ v (w,w))
  | Odd  (Vector_ (v,w) (w,w))
  
create x n = create_ () x n
create_ :: v -> w -> Int -> Vector_ v w
create_ v w n 
  | n==0   = Zero v
  | even n = Even (create_ v (w,w) (half n))
  | odd n  = Odd  (create_ (v,w) (w,w) (half n))

-----------------------------------------------------
-- To create rectangular arrays, we repeat the definition
-- and place vector at the leaf (Zero) node.

type Rect a = Rect_ () a
data Rect_ v w 
  = ZeroR (Vector v)
  | EvenR (Rect_ v (w,w))
  | OddR  (Rect_ (v,w) (w,w))
  
 

---------------------------------------------

newtype Empty a = E ()          -- the empty vector
newtype Id a = I a              -- the vector of size 1
newtype Pair v w a = P(v a,w a) -- vectors of size v + w

type Square a = Square_ Empty Id a
data Square_ v w a
  = ZeroS (v(v a))
  | EvenS (Square_ v (Pair w w) a)
  | OddS  (Square_ (Pair v w) (Pair w w) a)
  
  
f x = (EvenS (OddS (ZeroS x)))
g x y = P(E(),P(I x,I y))

row1 = P (E (),P(I 3,I 4))
row2 = P (E (),P(I 5,I 6))
table = P(E (),P(I row1, I row2))

z = EvenS(OddS (ZeroS table))

-- 4 by 4 array
h w x y z = P(E(),P(P(I w,I x),P(I y,I z)))
r1 = h 1 2 3 4
r2 = h 5 6 7 8
r3 = h 9 10 11 12
r4 = h 13 14 15 16
tab = h r1 r2 r3 r4
dd = EvenS(EvenS(OddS(ZeroS tab)))

------------------------------------
-- indexing functions

subE i (E ()) = error "no index in empty vector"

subI 0 (I x) = x
subI n (I x) = error "only 0 can index vector of size 1"

subP subv subw vsize i (P (v,w))
  | i < vsize = subv i v
  | i >= vsize = subw (i-vsize) w
  
sub (i,j) m = sub_ subE subI 0 1 (i,j) m


sub_ :: (forall b. Int -> v b -> b) ->
        (forall b. Int -> w b -> b) ->
        Int -> Int -> (Int,Int) -> Square_ v w a -> a
         
sub_ subv subw vsize wsize (i,j) x =
  case x of
    ZeroS vv -> subv i (subv j vv)
    EvenS m -> sub_ subv (subP subw subw wsize)
                    vsize (wsize+wsize) (i,j) m
    OddS m -> sub_ (subP subv subw vsize) (subP subw subw wsize)
                   (vsize+wsize) (wsize+wsize) (i,j) m

  
--