packages feed

casa-reoc-0.1.0.0: src/ReOC/Data/Transponder.hs

{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wall #-}
-- The checks of inheritance (inheritTransponder) have a constraint that their body does not use, by design.
{-# OPTIONS_GHC -Wno-redundant-constraints #-}

-- | The data type @Transponder@: whether a type of RPA is fitted with a transponder or ADS-B (out).
module ReOC.Data.Transponder (
  Transponder (..),
  TransponderLike (..),
  lawNamesTransponder,
  InheritTransponder,
  inheritTransponder,
) where

import Control.Lens (Choice, Optic, prism', review)
import Data.Functor.Const (Const)
import ReOC.Name.NoTransponder (NoTransponderLike (..))
import ReOC.Name.TransponderFitted (TransponderFittedLike (..))

-- | Whether a type of RPA is fitted with a transponder or ADS-B (out).
data Transponder
  = NoTransponder
  | TransponderFitted
  deriving (Eq, Ord, Show)

-- | The name of the data type @Transponder@.
class TransponderLike p f x x' where
  transponder ::
    Optic p f x x' Transponder Transponder

-- | Identity
instance (x' ~ Transponder) => TransponderLike p f Transponder x' where
  transponder = id

-- | Prism
instance (Choice p, Applicative f, x' ~ Transponder) => NoTransponderLike p f Transponder x' where
  noTransponder = prism' (\() -> NoTransponder) (\case NoTransponder -> Just (); TransponderFitted -> Nothing)

-- | Prism
instance (Choice p, Applicative f, x' ~ Transponder) => TransponderFittedLike p f Transponder x' where
  transponderFitted = prism' (\() -> TransponderFitted) (\case NoTransponder -> Nothing; TransponderFitted -> Just ())

{- | Rebuilds a value from the name of each field or constructor.

Laws:

> lawNamesTransponder == id
-}
lawNamesTransponder :: Transponder -> Transponder
lawNamesTransponder = \case
  NoTransponder -> review noTransponder ()
  TransponderFitted -> review transponderFitted ()

-- | The classes that a data type holding @Transponder@ in one field, or in one or more constructors, inherits.
type InheritTransponder s =
  ( TransponderLike (->) (Const ()) s s
  , NoTransponderLike (->) (Const ()) s s
  , TransponderFittedLike (->) (Const ()) s s
  )

-- | Checks that a data type inherits every class of @InheritTransponder@.
inheritTransponder :: (InheritTransponder s) => proxy s -> ()
inheritTransponder _ = ()