Using the typical definition of type-level naturals, I\'ve defined an n-dimensional grid.
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANG
So this turns out to be wrong. I'll leave it here in case anybody wants to try to fix it.
This implementation is the way @pigworker suggested I think. It compiles, but I haven't tested it. (I took the cojoin1
implementation from http://blog.sigfpe.com/2006/12/evaluating-cellular-automata-is.html)
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
data Nat = Z | S Nat
data U (n :: Nat) x where
Point :: x -> U Z x
Dimension :: [U n x] -> U n x -> [U n x] -> U (S n) x
unPoint :: U Z x -> x
unPoint (Point x) = x
dmap :: (U n x -> U m r) -> U (S n) x -> U (S m) r
dmap f (Dimension ls mid rs) = Dimension (map f ls) (f mid) (map f rs)
right, left :: U (S n) x -> U (S n) x
right (Dimension a b (c:cs)) = Dimension (b:a) c cs
left (Dimension (a:as) b c) = Dimension as a (b:c)
instance Functor (U n) where
fmap f (Point x) = Point (f x)
fmap f d@Dimension{} = dmap (fmap f) d
class Functor w => Comonad w where
(=>>) :: w a -> (w a -> b) -> w b
coreturn :: w a -> a
cojoin :: w a -> w (w a)
x =>> f = fmap f (cojoin x)
cojoin xx = xx =>> id
instance Comonad (U n) where
coreturn (Point x) = x
coreturn (Dimension _ mid _) = coreturn mid
cojoin (Point x) = Point (Point x)
cojoin d@Dimension{} = fmap unlayer . unlayer . fmap dist . cojoin1 . fmap cojoin . layer $ d
dist :: U (S Z) (U n x) -> U n (U (S Z) x)
dist = layerUnder . unlayer
layerUnder :: U (S n) x -> U n (U (S Z) x)
layerUnder d@(Dimension _ Point{} _) = Point d
layerUnder d@(Dimension _ Dimension{} _) = dmap layerUnder d
unlayer :: U (S Z) (U n x) -> U (S n) x
unlayer = dmap unPoint
layer :: U (S n) x -> U (S Z) (U n x)
layer = dmap Point
cojoin1 :: U (S Z) x -> U (S Z) (U (S Z) x)
cojoin1 a = layer $ Dimension (tail $ iterate left a) a (tail $ iterate right a)