-- | Free monad based directory layouts module System.Directory.Layout.Internal ( DL(..), Layout ) where import Control.Applicative (Applicative(..), (<$>)) import Data.Foldable (Foldable(..)) import Data.Traversable (Traversable(..), fmapDefault, foldMapDefault) import Data.Monoid (Monoid(..)) import Data.Default (Default(..)) import Data.Functor.Apply (Apply(..)) import Data.Functor.Bind (Bind(..)) import Data.Semigroup (Semigroup(..)) import Data.Text (Text) -- | Type synonym to save some acrobatics type Layout = DL () -- | Representation of directory layouts -- -- Invariants: -- -- * 'F' second argument is never @D _ _ _@ or @F _ _ _@ itself -- -- * 'F' third argument is never @T _ _@ -- -- * 'D' second argument is never @T _ _@ -- -- * 'D' third argument is never @T _ _@ data DL a = E !a -- ^ Emptyness, nothing found here | T !Text !a -- ^ File contents | F !FilePath !Layout !(DL a) -- ^ File node | D !FilePath !Layout !(DL a) -- ^ Directory node deriving (Show, Read, Eq, Ord) instance Default a => Default (DL a) where def = E def {-# INLINE def #-} instance Semigroup (DL a) where E _ <> b = b T _ _ <> b = b F f t l <> b = F f t (l <> b) D f l l' <> b = D f l (l' <> b) {-# INLINE (<>) #-} instance Default a => Monoid (DL a) where mempty = def {-# INLINE mempty #-} mappend = (<>) {-# INLINE mappend #-} instance Functor DL where fmap = fmapDefault {-# INLINE fmap #-} instance Apply DL where E f <.> E x = E (f x) E f <.> T t x = T t (f x) T t f <.> E x = T t (f x) T t f <.> T _ x = T t (f x) f <.> F fp c x = F fp c (f <.> x) f <.> D fp l x = D fp l (f <.> x) F fp c f <.> x = F fp c (f <.> x) D fp l f <.> x = D fp l (f <.> x) {-# INLINE (<.>) #-} instance Applicative DL where pure = E {-# INLINE pure #-} (<*>) = (<.>) {-# INLINE (<*>) #-} instance Bind DL where E x >>- f = f x T _ x >>- f = f x F fp c x >>- f = F fp c (x >>- f) D fp x y >>- f = D fp x (y >>- f) {-# INLINE (>>-) #-} instance Monad DL where return = pure {-# INLINE return #-} (>>=) = (>>-) {-# INLINE (>>=) #-} instance Foldable DL where foldMap = foldMapDefault {-# INLINE foldMap #-} instance Traversable DL where traverse f (E x) = E <$> f x traverse f (T t x) = T t <$> f x traverse f (F fp t x) = F fp t <$> traverse f x traverse f (D fp x y) = D fp x <$> traverse f y {-# INLINE traverse #-}