module Data.Apart.Shape (Shape (..)) where import Data.Bifoldable (Bifoldable (..)) import Data.Bifunctor (Bifunctor (..)) import Data.Bitraversable (Bitraversable (..)) import Data.Functor.Apply (Apply (..)) import Data.Functor.Alt (Alt (..)) import Data.Semigroup (Semigroup (..)) -- | Type that can tell you about aggregate state of your structure. data Shape t raw value = Ready (t value) -- ^ Segment of values in memory | Converted raw -- ^ Segment of values somewhere else instance (Show (t value), Show value, Show raw) => Show (Shape t raw value) where show (Ready values) = show values show (Converted raw) = "{" <> show raw <> "}" instance Functor t => Functor (Shape t raw) where fmap f (Ready values) = Ready $ f <$> values fmap f (Converted raw) = Converted raw instance Apply t => Apply (Shape t raw) where Ready fs <.> Ready xs = Ready $ fs <.> xs Ready fs <.> Converted raw = Converted raw Converted raw <.> _ = Converted raw instance Alt t => Alt (Shape t raw) where Converted raw x = x Ready xs _ = Ready xs instance Foldable t => Foldable (Shape t raw) where foldr f acc (Ready values) = foldr f acc values foldr f acc (Converted raw) = acc instance Traversable t => Traversable (Shape t raw) where traverse f (Ready values) = Ready <$> traverse f values traverse _ (Converted raw) = pure $ Converted raw instance Functor t => Bifunctor (Shape t) where bimap _ f (Ready values) = Ready $ f <$> values bimap g _ (Converted raw) = Converted $ g raw instance Foldable t => Bifoldable (Shape t) where bifoldr _ f acc (Ready values) = foldr f acc values bifoldr g _ acc (Converted raw) = g raw acc instance Traversable t => Bitraversable (Shape t) where bitraverse _ f (Ready values) = Ready <$> traverse f values bitraverse g _ (Converted raw) = Converted <$> g raw