packages feed

filepather-0.8.0.0: src/System/FilePather/Step.hs

{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wall #-}

{- | One application of a named build step to a file.

A 'Step' is a product: its fields are named 'stepName' and 'stepInput'.
-}
module System.FilePather.Step (
  -- * Type
  Step (..),

  -- * Optics
  StepLike (..),
  lawNamesStep,
  InheritStep,
  inheritStep,
) where

import Control.DeepSeq (NFData)
import Control.Lens (Optic, cloneLens, view)
import Data.Data (Data)
import Data.Functor.Const (Const)
import GHC.Generics (Generic)
import System.FilePather.Name.StepInput (StepInputLike (..))
import System.FilePather.Name.StepName (StepNameLike (..))

{- $setup
>>> import Control.Lens (cloneLens, view)
-}

{- | One application of a named build step to a file: the name of the step
('stepName'), such as @"pdf page 1"@, and its input file ('stepInput').

>>> view (cloneLens stepName) (Step "pdf page 1" "public/a.pdf")
"pdf page 1"

>>> view (cloneLens stepInput) (Step "pdf page 1" "public/a.pdf")
"public/a.pdf"

@since 0.7.0.0
-}
data Step
  = Step String FilePath
  deriving stock (Eq, Ord, Show, Generic, Data)
  deriving anyclass (NFData)

{- | The class of 'Step'.

@since 0.8.0.0
-}
class StepLike p f x x' where
  step ::
    Optic p f x x' Step Step

{- | Identity

@since 0.8.0.0
-}
instance (x' ~ Step) => StepLike p f Step x' where
  step =
    id
  {-# INLINE step #-}

{- | Lens

@since 0.8.0.0
-}
instance (p ~ (->), Functor f, x' ~ Step) => StepNameLike p f Step x' where
  stepName f (Step n i) =
    fmap (`Step` i) (f n)
  {-# INLINE stepName #-}

{- | Lens

@since 0.8.0.0
-}
instance (p ~ (->), Functor f, x' ~ Step) => StepInputLike p f Step x' where
  stepInput f (Step n i) =
    fmap (Step n) (f i)
  {-# INLINE stepInput #-}

{- | Rebuild a value using only the name of each field.

Laws:

> lawNamesStep == id

@since 0.8.0.0
-}
lawNamesStep :: Step -> Step
lawNamesStep s =
  Step (view (cloneLens stepName) s) (view (cloneLens stepInput) s)

{- | The classes that a data type holding 'Step' inherits.

@since 0.8.0.0
-}
type InheritStep s =
  ( StepLike (->) (Const ()) s s
  , StepNameLike (->) (Const ()) s s
  , StepInputLike (->) (Const ()) s s
  )

{- | Check, where it is applied, that @s@ inherits every name of 'Step'.

@since 0.8.0.0
-}
inheritStep :: (InheritStep s) => proxy s -> ()
inheritStep _ =
  ()