packages feed

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

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

-- | The data type @RadioQualification@: the qualification of the chief remote pilot to use an aeronautical radio.
module ReOC.Data.RadioQualification (
  RadioQualification (..),
  RadioQualificationLike (..),
  lawNamesRadioQualification,
  InheritRadioQualification,
  inheritRadioQualification,
) where

import Control.Lens (Choice, Optic, prism', review)
import Data.Functor.Const (Const)
import ReOC.Name.FlightCrewLicence (FlightCrewLicenceLike (..))
import ReOC.Name.NoRadioQualification (NoRadioQualificationLike (..))
import ReOC.Name.RadioOperatorCertificate (RadioOperatorCertificateLike (..))

-- | The qualification of the chief remote pilot to use an aeronautical radio.
data RadioQualification
  = FlightCrewLicence
  | RadioOperatorCertificate
  | NoRadioQualification
  deriving (Eq, Ord, Show)

-- | The name of the data type @RadioQualification@.
class RadioQualificationLike p f x x' where
  radioQualification ::
    Optic p f x x' RadioQualification RadioQualification

-- | Identity
instance (x' ~ RadioQualification) => RadioQualificationLike p f RadioQualification x' where
  radioQualification = id

-- | Prism
instance (Choice p, Applicative f, x' ~ RadioQualification) => FlightCrewLicenceLike p f RadioQualification x' where
  flightCrewLicence = prism' (\() -> FlightCrewLicence) (\case FlightCrewLicence -> Just (); RadioOperatorCertificate -> Nothing; NoRadioQualification -> Nothing)

-- | Prism
instance (Choice p, Applicative f, x' ~ RadioQualification) => RadioOperatorCertificateLike p f RadioQualification x' where
  radioOperatorCertificate = prism' (\() -> RadioOperatorCertificate) (\case FlightCrewLicence -> Nothing; RadioOperatorCertificate -> Just (); NoRadioQualification -> Nothing)

-- | Prism
instance (Choice p, Applicative f, x' ~ RadioQualification) => NoRadioQualificationLike p f RadioQualification x' where
  noRadioQualification = prism' (\() -> NoRadioQualification) (\case FlightCrewLicence -> Nothing; RadioOperatorCertificate -> Nothing; NoRadioQualification -> Just ())

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

Laws:

> lawNamesRadioQualification == id
-}
lawNamesRadioQualification :: RadioQualification -> RadioQualification
lawNamesRadioQualification = \case
  FlightCrewLicence -> review flightCrewLicence ()
  RadioOperatorCertificate -> review radioOperatorCertificate ()
  NoRadioQualification -> review noRadioQualification ()

-- | The classes that a data type holding @RadioQualification@ in one field, or in one or more constructors, inherits.
type InheritRadioQualification s =
  ( RadioQualificationLike (->) (Const ()) s s
  , FlightCrewLicenceLike (->) (Const ()) s s
  , RadioOperatorCertificateLike (->) (Const ()) s s
  , NoRadioQualificationLike (->) (Const ()) s s
  )

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