This is just an additional thought following upon Daniel. It looked like your Grids were only of Colors It probably won't do much for a small 'Grid' but it is comparatively easy to make an Unbox instance for Color. Then a grid will contain an unboxed array. In Grid.hs you would import Data.Vector.Unboxed rather than Data.Vector. This is in general much better for many reasons, but will require you to put an Unbox a => constraint on many of the definitions. This might have consequences if you want to make or 'map' into Grids full of things of another type than Color, unless it has an Unbox instance.
Below I just add the TH incantation from vector-th-unbox (I just learned about that package recently, and am taking the occasion to test it again) and the two requisite definitions. It wouldn't be much harder to write it by hand following the Bool instance in Data.Vector.Unboxed.Base.
{-#LANGUAGE TemplateHaskell, TypeFamilies, MultiParamTypeClasses#-}
module Color where
import Display
import Data.Vector.Unboxed.Deriving
import qualified Data.Vector.Unboxed as V
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Generic.Mutable as M
import Data.Word (Word8)
data Color = Yellow | Red | Green | Blue | Empty
deriving (Show, Eq, Ord, Enum, Bounded)
fromColor :: Color -> Word8
{-# INLINE fromColor #-}
fromColor = fromIntegral . fromEnum
toColor :: Word8 -> Color
{-# INLINE toColor #-}
toColor x | x < 5 = toEnum (fromIntegral x)
toColor _ = Empty
derivingUnbox "Color"
[t| Color -> Word8 |]
[| fromColor |]
[| toColor |]
-- test
colorCycle :: Int -> V.Vector Color
colorCycle n = V.unfoldr colorop 0 where
colorop m | m < n = Just (toColor (fromIntegral (m `mod` 5)),m+1)
colorop _ = Nothing
-- *Colour> colorCycle 12
-- fromList [Yellow,Red,Green,Blue,Empty,Yellow,
-- Red,Green,Blue,Empty,Yellow,Red]
colorBlack = "\ESC[0;30m"
colorRed = "\ESC[0;31m"
colorGreen = "\ESC[0;32m"
colorYellow = "\ESC[0;33m"
colorBlue = "\ESC[0;34m"
instance Display Color where
display Red = colorRed ++ "R" ++ colorBlack
display Green = colorGreen ++ "G" ++ colorBlack
display Yellow = colorYellow ++ "Y" ++ colorBlack
display Blue = colorBlue ++ "B" ++ colorBlack
display Empty = "."
Edit: In versions of vector-th-unbox preceding 0.1 the following template was used:
derivingUnbox "Color"
[d| instance Unbox' (Color) Word8 |]
[| fromColor |]
[| toColor |]