document-build-0.2.0.0: src/Document/Build/Target.hs
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wall #-}
{- | What a build is running the rules on.
A 'Target' is a sum: its constructors are named 'targetFile',
'targetDirectory' and 'targetComplete'.
-}
module Document.Build.Target (
-- * Type
KnownFiles,
Target (..),
-- * Optics
TargetLike (..),
lawNamesTarget,
InheritTarget,
inheritTarget,
) where
import Control.DeepSeq (NFData)
import Control.Lens (Choice, Optic, prism', review)
import Data.Data (Data)
import Data.Functor.Const (Const)
import Data.Map (Map)
import Document.Build.Name.TargetComplete (TargetCompleteLike (..))
import Document.Build.Name.TargetDirectory (TargetDirectoryLike (..))
import Document.Build.Name.TargetFile (TargetFileLike (..))
import GHC.Generics (Generic)
import System.FilePather.Trail (Trail)
{- $setup
>>> import Control.Lens (preview)
-}
{- | The files that a build knows: the files of its input directories, with
the empty trail, and the files that the rules made, with their trails, by
normalised path.
@since 0.1.0.0
-}
type KnownFiles = Map FilePath Trail
{- | What a build is running the rules on.
>>> preview targetComplete (TargetComplete mempty)
Just (fromList [])
@since 0.1.0.0
-}
data Target
= -- | A file: a file of an input directory, or a file the rules made
-- ('targetFile').
TargetFile
| -- | A directory of the output directory ('targetDirectory').
TargetDirectory
| -- | The output directory, once, when the rules make no more files, with
-- every file the build knows ('targetComplete').
TargetComplete KnownFiles
deriving stock (Eq, Ord, Show, Generic, Data)
deriving anyclass (NFData)
{- | The class of 'Target'.
@since 0.2.0.0
-}
class TargetLike p f x x' where
target ::
Optic p f x x' Target Target
{- | Identity
@since 0.2.0.0
-}
instance (x' ~ Target) => TargetLike p f Target x' where
target =
id
{-# INLINE target #-}
{- | Prism
@since 0.2.0.0
-}
instance (Choice p, Applicative f, x' ~ Target) => TargetFileLike p f Target x' where
targetFile =
prism'
(\() -> TargetFile)
( \case
TargetFile -> Just ()
TargetDirectory -> Nothing
TargetComplete _ -> Nothing
)
{-# INLINE targetFile #-}
{- | Prism
@since 0.2.0.0
-}
instance (Choice p, Applicative f, x' ~ Target) => TargetDirectoryLike p f Target x' where
targetDirectory =
prism'
(\() -> TargetDirectory)
( \case
TargetDirectory -> Just ()
TargetFile -> Nothing
TargetComplete _ -> Nothing
)
{-# INLINE targetDirectory #-}
{- | Prism
@since 0.2.0.0
-}
instance (Choice p, Applicative f, x' ~ Target) => TargetCompleteLike p f Target x' where
targetComplete =
prism'
TargetComplete
( \case
TargetComplete k -> Just k
TargetFile -> Nothing
TargetDirectory -> Nothing
)
{-# INLINE targetComplete #-}
{- | Rebuild a value using only the name of each constructor.
Laws:
> lawNamesTarget == id
@since 0.2.0.0
-}
lawNamesTarget :: Target -> Target
lawNamesTarget = \case
TargetFile -> review targetFile ()
TargetDirectory -> review targetDirectory ()
TargetComplete k -> review targetComplete k
{- | The classes that a data type holding 'Target' inherits.
@since 0.2.0.0
-}
type InheritTarget s =
( TargetLike (->) (Const ()) s s
, TargetFileLike (->) (Const ()) s s
, TargetDirectoryLike (->) (Const ()) s s
, TargetCompleteLike (->) (Const ()) s s
)
{- | Check, where it is applied, that @s@ inherits every name of 'Target'.
@since 0.2.0.0
-}
inheritTarget :: (InheritTarget s) => proxy s -> ()
inheritTarget _ =
()