content: {-# LANGUAGE DerivingVia #-}
  {-# LANGUAGE UndecidableInstances #-}
  
  -- | The `RenderableVertices` class describes which values of type @a@ should
  -- be rendered when drawing a graph (or a topology) with vertices of type @a@
  module Crem.Render.RenderableVertices where
  
  import "base" Data.Functor.Const (Const (..))
  import "base" Data.Functor.Identity (Identity (..))
  import "base" Data.Monoid (Dual (..), Product (..), Sum (..))
  import "base" Data.Ord (Down (..))
  import "base" Data.Proxy (Proxy (..))
  import "base" Data.Semigroup (All (..), Any (..), First (..), Last (..), Max (..), Min (..))
  import "base" Data.Void (Void)
  
  -- | The `RenderableVertices` class is implemented just as a list of elements
  -- of type @a@.
  class RenderableVertices a where
    vertices :: [a]
  
  -- | This is a newtype to be used with `deriving via`. If @a@ has instances for
  -- `Enum` and `Bounded`, then `AllVertices a` has an instance of
  -- `RenderableVertices` which lists all the terms of type @a@.
  newtype AllVertices a = AllVertices a
  
  instance (Enum a, Bounded a) => RenderableVertices (AllVertices a) where
    vertices :: [AllVertices a]
    vertices = AllVertices <$> [minBound .. maxBound]
  
  instance RenderableVertices Void where
    vertices :: [Void]
    vertices = []
  
  deriving via AllVertices () instance RenderableVertices ()
  
  deriving via AllVertices Bool instance RenderableVertices Bool
  
  deriving newtype instance RenderableVertices All
  
  deriving newtype instance RenderableVertices Any
  
  deriving via AllVertices Ordering instance RenderableVertices Ordering
  
  instance (RenderableVertices a) => RenderableVertices (Maybe a) where
    vertices :: [Maybe a]
    vertices =
      Nothing : (Just <$> vertices)
  
  deriving newtype instance (RenderableVertices a) => RenderableVertices (Min a)
  
  deriving newtype instance (RenderableVertices a) => RenderableVertices (Max a)
  
  deriving newtype instance (RenderableVertices a) => RenderableVertices (First a)
  
  deriving newtype instance (RenderableVertices a) => RenderableVertices (Last a)
  
  deriving newtype instance (RenderableVertices a) => RenderableVertices (Identity a)
  
  deriving newtype instance (RenderableVertices a) => RenderableVertices (Dual a)
  
  deriving newtype instance (RenderableVertices a) => RenderableVertices (Sum a)
  
  deriving newtype instance (RenderableVertices a) => RenderableVertices (Down a)
  
  deriving newtype instance (RenderableVertices a) => RenderableVertices (Product a)
  
  instance RenderableVertices (Proxy a) where
    vertices :: [Proxy a]
    vertices = [Proxy]
  
  deriving newtype instance (RenderableVertices a) => RenderableVertices (Const a b)
  
  instance (RenderableVertices a, RenderableVertices b) => RenderableVertices (Either a b) where
    vertices :: [Either a b]
    vertices =
      (Left <$> vertices)
        <> (Right <$> vertices)
  
  instance (RenderableVertices a, RenderableVertices b) => RenderableVertices (a, b) where
    vertices :: [(a, b)]
    vertices = [(a, b) | a <- vertices, b <- vertices]
  
  instance (RenderableVertices a, RenderableVertices b, RenderableVertices c) => RenderableVertices (a, b, c) where
    vertices :: [(a, b, c)]
    vertices = [(a, b, c) | a <- vertices, b <- vertices, c <- vertices]
  
  instance (RenderableVertices a, RenderableVertices b, RenderableVertices c, RenderableVertices d) => RenderableVertices (a, b, c, d) where
    vertices :: [(a, b, c, d)]
    vertices = [(a, b, c, d) | a <- vertices, b <- vertices, c <- vertices, d <- vertices]
  
  instance (RenderableVertices a, RenderableVertices b, RenderableVertices c, RenderableVertices d, RenderableVertices e) => RenderableVertices (a, b, c, d, e) where
    vertices :: [(a, b, c, d, e)]
    vertices = [(a, b, c, d, e) | a <- vertices, b <- vertices, c <- vertices, d <- vertices, e <- vertices]
  
  instance (RenderableVertices a, RenderableVertices b, RenderableVertices c, RenderableVertices d, RenderableVertices e, RenderableVertices f) => RenderableVertices (a, b, c, d, e, f) where
    vertices :: [(a, b, c, d, e, f)]
    vertices = [(a, b, c, d, e, f) | a <- vertices, b <- vertices, c <- vertices, d <- vertices, e <- vertices, f <- vertices]
  
  instance (RenderableVertices a, RenderableVertices b, RenderableVertices c, RenderableVertices d, RenderableVertices e, RenderableVertices f, RenderableVertices g) => RenderableVertices (a, b, c, d, e, f, g) where
    vertices :: [(a, b, c, d, e, f, g)]
    vertices = [(a, b, c, d, e, f, g) | a <- vertices, b <- vertices, c <- vertices, d <- vertices, e <- vertices, f <- vertices, g <- vertices]
  
  instance (RenderableVertices a, RenderableVertices b, RenderableVertices c, RenderableVertices d, RenderableVertices e, RenderableVertices f, RenderableVertices g, RenderableVertices h) => RenderableVertices (a, b, c, d, e, f, g, h) where
    vertices :: [(a, b, c, d, e, f, g, h)]
    vertices = [(a, b, c, d, e, f, g, h) | a <- vertices, b <- vertices, c <- vertices, d <- vertices, e <- vertices, f <- vertices, g <- vertices, h <- vertices]
  