{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE MonoLocalBinds #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE UndecidableInstances #-} module SizedGrid.Grid.Class where import SizedGrid.Coord import SizedGrid.Coord.Class import SizedGrid.Grid.Focused import SizedGrid.Grid.Grid import Control.Lens hiding (index) import Data.Functor.Rep #if MIN_VERSION_base(4,11,0) #else import Data.Semigroup hiding (All (..)) #endif import Generics.SOP -- | Conversion between `Grid` and `FocusedGrid` and access grids at a `Coord` class IsGrid cs grid | grid -> cs where -- | Get the element at a grid location. This is a lens because we know it must exist gridIndex :: Coord cs -> Lens' (grid a) a -- | Convert to, or run a function over, a `Grid` asGrid :: Lens' (grid a) (Grid cs a) -- | Convert to, or run a function over, a `FocusedGrid` asFocusedGrid :: Lens' (grid a) (FocusedGrid cs a) instance (AllSizedKnown cs, All IsCoordLifted cs) => IsGrid cs (Grid cs) where gridIndex coord = lens (\g -> index g coord) (\(Grid v) a -> Grid (v & ix (coordPosition coord) .~ a)) asGrid = id asFocusedGrid = lens (\g -> FocusedGrid g zeroCoord) (\_ fg -> focusedGrid fg) instance (AllSizedKnown cs, All IsCoordLifted cs) => IsGrid cs (FocusedGrid cs) where gridIndex c = (\f (FocusedGrid g p) -> (\g' -> FocusedGrid g' p) <$> f g) . gridIndex c asGrid = lens focusedGrid (\(FocusedGrid _ p) g -> FocusedGrid g p) asFocusedGrid = id