packages feed

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

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

-- | The data type @KeyPosition@: a key position of the operator that can own a risk.
module ReOC.Data.KeyPosition (
  KeyPosition (..),
  KeyPositionLike (..),
  lawNamesKeyPosition,
  InheritKeyPosition,
  inheritKeyPosition,
) where

import Control.Lens (Choice, Optic, prism', review)
import Data.Functor.Const (Const)
import ReOC.Name.ChiefExecutiveOfficer (ChiefExecutiveOfficerLike (..))
import ReOC.Name.ChiefRemotePilot (ChiefRemotePilotLike (..))
import ReOC.Name.MaintenanceController (MaintenanceControllerLike (..))

-- | A key position of the operator that can own a risk.
data KeyPosition
  = ChiefExecutiveOfficer
  | ChiefRemotePilot
  | MaintenanceController
  deriving (Eq, Ord, Show)

-- | The name of the data type @KeyPosition@.
class KeyPositionLike p f x x' where
  keyPosition ::
    Optic p f x x' KeyPosition KeyPosition

-- | Identity
instance (x' ~ KeyPosition) => KeyPositionLike p f KeyPosition x' where
  keyPosition = id

-- | Prism
instance (Choice p, Applicative f, x' ~ KeyPosition) => ChiefExecutiveOfficerLike p f KeyPosition x' where
  chiefExecutiveOfficer = prism' (\() -> ChiefExecutiveOfficer) (\case ChiefExecutiveOfficer -> Just (); ChiefRemotePilot -> Nothing; MaintenanceController -> Nothing)

-- | Prism
instance (Choice p, Applicative f, x' ~ KeyPosition) => ChiefRemotePilotLike p f KeyPosition x' where
  chiefRemotePilot = prism' (\() -> ChiefRemotePilot) (\case ChiefExecutiveOfficer -> Nothing; ChiefRemotePilot -> Just (); MaintenanceController -> Nothing)

-- | Prism
instance (Choice p, Applicative f, x' ~ KeyPosition) => MaintenanceControllerLike p f KeyPosition x' where
  maintenanceController = prism' (\() -> MaintenanceController) (\case ChiefExecutiveOfficer -> Nothing; ChiefRemotePilot -> Nothing; MaintenanceController -> Just ())

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

Laws:

> lawNamesKeyPosition == id
-}
lawNamesKeyPosition :: KeyPosition -> KeyPosition
lawNamesKeyPosition = \case
  ChiefExecutiveOfficer -> review chiefExecutiveOfficer ()
  ChiefRemotePilot -> review chiefRemotePilot ()
  MaintenanceController -> review maintenanceController ()

-- | The classes that a data type holding @KeyPosition@ in one field, or in one or more constructors, inherits.
type InheritKeyPosition s =
  ( KeyPositionLike (->) (Const ()) s s
  , ChiefExecutiveOfficerLike (->) (Const ()) s s
  , ChiefRemotePilotLike (->) (Const ()) s s
  , MaintenanceControllerLike (->) (Const ()) s s
  )

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