filepather-0.8.0.0: src/System/FilePather/ReproducesInput.hs
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wall #-}
{- | A step that would make a file that is already in its chain.
A 'ReproducesInput' is a product: its fields are named 'file', 'step' and
'trail'. It holds a 'Step' and a 'Trail', so it inherits their names.
-}
module System.FilePather.ReproducesInput (
-- * Type
ReproducesInput (..),
-- * Optics
ReproducesInputLike (..),
lawNamesReproducesInput,
InheritReproducesInput,
inheritReproducesInput,
inheritsReproducesInput,
) where
import Control.DeepSeq (NFData)
import Control.Lens (Optic, cloneLens, view)
import Data.Data (Data)
import Data.Functor.Const (Const)
import Data.Proxy (Proxy (..))
import GHC.Generics (Generic)
import System.FilePather.Name.File (FileLike (..))
import System.FilePather.Name.StepInput (StepInputLike (..))
import System.FilePather.Name.StepName (StepNameLike (..))
import System.FilePather.Name.Steps (StepsLike (..))
import System.FilePather.Step (Step, StepLike (..), inheritStep)
import System.FilePather.Trail (Trail, TrailLike (..), inheritTrail)
{- | A step would make a file that is already in its chain: the file
('file'), which is its input file or the input file of a step in the trail,
the step ('step'), and the trail of its input file ('trail').
@since 0.8.0.0
-}
data ReproducesInput
= ReproducesInput FilePath Step Trail
deriving stock (Eq, Ord, Show, Generic, Data)
deriving anyclass (NFData)
{- | The class of 'ReproducesInput'.
@since 0.8.0.0
-}
class ReproducesInputLike p f x x' where
reproducesInput ::
Optic p f x x' ReproducesInput ReproducesInput
{- | Identity
@since 0.8.0.0
-}
instance (x' ~ ReproducesInput) => ReproducesInputLike p f ReproducesInput x' where
reproducesInput =
id
{-# INLINE reproducesInput #-}
{- | Lens
@since 0.8.0.0
-}
instance (p ~ (->), Functor f, x' ~ ReproducesInput) => FileLike p f ReproducesInput x' where
file f (ReproducesInput o s t) =
fmap (\o' -> ReproducesInput o' s t) (f o)
{-# INLINE file #-}
{- | Lens: 'step' is the default name of the field of type 'Step'.
@since 0.8.0.0
-}
instance (p ~ (->), Functor f, x' ~ ReproducesInput) => StepLike p f ReproducesInput x' where
step f (ReproducesInput o s t) =
fmap (\s' -> ReproducesInput o s' t) (f s)
{-# INLINE step #-}
{- | Lens: 'trail' is the default name of the field of type 'Trail'.
@since 0.8.0.0
-}
instance (p ~ (->), Functor f, x' ~ ReproducesInput) => TrailLike p f ReproducesInput x' where
trail f (ReproducesInput o s t) =
fmap (ReproducesInput o s) (f t)
{-# INLINE trail #-}
{- | Lens: through 'step', a lens, then 'Step''s 'stepName', a lens.
@since 0.8.0.0
-}
instance (p ~ (->), Functor f, x' ~ ReproducesInput) => StepNameLike p f ReproducesInput x' where
stepName =
step . stepName
{-# INLINE stepName #-}
{- | Lens: through 'step', a lens, then 'Step''s 'stepInput', a lens.
@since 0.8.0.0
-}
instance (p ~ (->), Functor f, x' ~ ReproducesInput) => StepInputLike p f ReproducesInput x' where
stepInput =
step . stepInput
{-# INLINE stepInput #-}
{- | Lens: through 'trail', a lens, then 'Trail''s 'steps', a lens.
@since 0.8.0.0
-}
instance (p ~ (->), Functor f, x' ~ ReproducesInput) => StepsLike p f ReproducesInput x' where
steps =
trail . steps
{-# INLINE steps #-}
{- | Rebuild a value using only the name of each field.
Laws:
> lawNamesReproducesInput == id
@since 0.8.0.0
-}
lawNamesReproducesInput :: ReproducesInput -> ReproducesInput
lawNamesReproducesInput s =
ReproducesInput (view (cloneLens file) s) (view (cloneLens step) s) (view (cloneLens trail) s)
{- | The classes that a data type holding 'ReproducesInput' inherits.
@since 0.8.0.0
-}
type InheritReproducesInput s =
( ReproducesInputLike (->) (Const ()) s s
, FileLike (->) (Const ()) s s
, StepLike (->) (Const ()) s s
, TrailLike (->) (Const ()) s s
, StepNameLike (->) (Const ()) s s
, StepInputLike (->) (Const ()) s s
, StepsLike (->) (Const ()) s s
)
{- | Check, where it is applied, that @s@ inherits every name of
'ReproducesInput'.
@since 0.8.0.0
-}
inheritReproducesInput :: (InheritReproducesInput s) => proxy s -> ()
inheritReproducesInput _ =
()
{- | 'ReproducesInput' inherits every name of 'Step' and of 'Trail'.
@since 0.8.0.0
-}
inheritsReproducesInput :: [()]
inheritsReproducesInput =
let p = Proxy :: Proxy ReproducesInput
in [inheritStep p, inheritTrail p]