packages feed

filepather-0.4.0: src/System/FilePath/FilePather/ReadFilePath.hs

{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

module System.FilePath.FilePather.ReadFilePath(
  ReadFilePathT(..)
, ReadFilePath
, ReadFilePathT1
, ReadFilePath1
, readFilePath
, hoistReadFilePath
, liftReadFilePath
) where

import Control.Applicative
    ( Applicative(liftA2, (<*>), pure), Alternative((<|>), empty) )
import Control.Category((.))
import Control.Lens
    ( iso, Iso, Rewrapped, Wrapped(Unwrapped, _Wrapped'), view, _Wrapped, ( # ) )
import Control.Monad
    ( Monad((>>=), return), Functor(fmap), MonadPlus(mplus, mzero) )
import Control.Monad.Cont.Class ( MonadCont(callCC) )
import Control.Monad.Error.Class ( MonadError(throwError, catchError) )
import Control.Monad.Fail ( MonadFail(fail) )
import Control.Monad.Fix ( MonadFix(mfix) )
import Control.Monad.IO.Class ( MonadIO(liftIO) )
import Control.Monad.Morph ( MFunctor(hoist), MMonad(embed) )
import Control.Monad.Reader.Class ( MonadReader(reader, local, ask) )
import Control.Monad.State.Class ( MonadState(state, get, put) )
import Control.Monad.Trans.Class(MonadTrans(lift))
import Control.Monad.Writer.Class ( MonadWriter(pass, tell, writer, listen) )
import Control.Monad.Zip ( MonadZip(mzipWith) )
import Data.Functor.Apply ( Apply(liftF2, (<.>)) )
import Data.Functor.Alt ( Alt((<!>)) )
import Data.Functor.Bind ( Bind((>>-)) )
import Data.Functor.Identity(Identity(Identity, runIdentity))
import Data.Monoid(Monoid(mappend, mempty))
import Data.Semigroup(Semigroup((<>)))
import System.FilePath(FilePath)

newtype ReadFilePathT f a =
  ReadFilePathT (FilePath -> f a)

instance ReadFilePathT f a ~ t =>
  Rewrapped (ReadFilePathT f' a') t

instance Wrapped (ReadFilePathT f a) where
  type Unwrapped (ReadFilePathT f a) =
    FilePath
    -> f a
  _Wrapped' =
    iso (\(ReadFilePathT x) -> x) ReadFilePathT
  {-# INLINE _Wrapped' #-}

type ReadFilePath a =
  ReadFilePathT Identity a

type ReadFilePathT1 f =
  ReadFilePathT f ()

type ReadFilePath1 f =
  ReadFilePath ()

readFilePath ::
  Iso
    (ReadFilePath a)
    (ReadFilePath a')
    (FilePath -> a)
    (FilePath -> a')
readFilePath =
  iso
    (\(ReadFilePathT x) -> runIdentity . x)
    (\p -> ReadFilePathT (Identity . p))
{-# INLINE readFilePath #-}

instance (Apply f, Semigroup a) => Semigroup (ReadFilePathT f a) where
  ReadFilePathT a <> ReadFilePathT b =
    ReadFilePathT (\p -> liftF2 (<>) (a p) (b p))
  {-# INLINE (<>) #-}

instance (Apply f, Applicative f, Monoid a) => Monoid (ReadFilePathT f a) where
  ReadFilePathT a `mappend` ReadFilePathT b =
    ReadFilePathT (\p -> liftA2 mappend (a p) (b p))
  {-# INLINE mappend #-}
  mempty =
    ReadFilePathT (pure (pure mempty))
  {-# INLINE mempty #-}

instance Functor f => Functor (ReadFilePathT f) where
  fmap f (ReadFilePathT x) =
    ReadFilePathT (fmap (fmap f) x)
  {-# INLINE fmap #-}

instance Apply f => Apply (ReadFilePathT f) where
  ReadFilePathT f <.> ReadFilePathT a =
    ReadFilePathT (\p -> f p <.> a p)
  {-# INLINE (<.>) #-}

instance Bind f => Bind (ReadFilePathT f) where
  ReadFilePathT f >>- g =
    ReadFilePathT (\p -> f p >>- \a -> view _Wrapped (g a) p)
  {-# INLINE (>>-) #-}

instance Applicative f => Applicative (ReadFilePathT f) where
  ReadFilePathT f <*> ReadFilePathT a =
    ReadFilePathT (\p -> f p <*> a p)
  {-# INLINE (<*>) #-}
  pure =
    ReadFilePathT . pure . pure
  {-# INLINE pure #-}

instance Alt f => Alt (ReadFilePathT f) where
  ReadFilePathT a <!> ReadFilePathT b =
    ReadFilePathT (\p -> a p <!> b p)
  {-# INLINE (<!>) #-}

instance Alternative f => Alternative (ReadFilePathT f) where
  ReadFilePathT a <|> ReadFilePathT b =
    ReadFilePathT (\p -> a p <|> b p)
  {-# INLINE (<|>) #-}
  empty =
    ReadFilePathT (pure empty)
  {-# INLINE empty #-}

instance Monad f => Monad (ReadFilePathT f) where
  ReadFilePathT f >>= g =
    ReadFilePathT (\p -> f p >>= \a -> view _Wrapped (g a) p)
  {-# INLINE (>>=) #-}
  return =
    ReadFilePathT . return . return
  {-# INLINE return #-}

instance MonadTrans ReadFilePathT where
  lift =
    ReadFilePathT . pure
  {-# INLINE lift #-}

instance MonadIO f => MonadIO (ReadFilePathT f) where
  liftIO =
    ReadFilePathT . pure . liftIO
  {-# INLINE liftIO #-}

instance MFunctor ReadFilePathT where
  hoist k (ReadFilePathT f) =
    ReadFilePathT (k .f)
  {-# INLINE hoist #-}

instance MMonad ReadFilePathT where
  embed k (ReadFilePathT f) =
    ReadFilePathT (\p -> view _Wrapped (k (f p)) p)
  {-# INLINE embed #-}

instance Monad f => MonadReader FilePath (ReadFilePathT f) where
  ask =
    ReadFilePathT pure
  {-# INLINE ask #-}
  local k (ReadFilePathT f) =
    ReadFilePathT (f . k)
  {-# INLINE local #-}
  reader k =
    ReadFilePathT (pure . k)
  {-# INLINE reader #-}

instance MonadState FilePath f => MonadState FilePath (ReadFilePathT f) where
  state =
    lift . state
  {-# INLINE state #-}
  get =
    lift get
  {-# INLINE get #-}
  put =
    lift . put
  {-# INLINE put #-}

instance MonadWriter FilePath f => MonadWriter FilePath (ReadFilePathT f) where
  writer =
    lift . writer
  {-# INLINE writer #-}
  tell =
    lift . tell
  {-# INLINE tell #-}
  listen (ReadFilePathT f) =
    ReadFilePathT (listen . f)
  {-# INLINE listen #-}
  pass (ReadFilePathT f) =
    ReadFilePathT (pass . f)
  {-# INLINE pass #-}

instance MonadFail f => MonadFail (ReadFilePathT f) where
  fail =
    lift . fail
  {-# INLINE fail #-}

instance MonadFix f => MonadFix (ReadFilePathT f) where
  mfix f =
    ReadFilePathT (\p -> mfix (\a -> view _Wrapped (f a) p))
  {-# INLINE mfix #-}

instance MonadZip f => MonadZip (ReadFilePathT f) where
  mzipWith f (ReadFilePathT m) (ReadFilePathT n) =
    ReadFilePathT (\a -> mzipWith f (m a) (n a))
  {-# INLINE mzipWith #-}

instance MonadCont f => MonadCont (ReadFilePathT f) where
  callCC p =
    ReadFilePathT (\r -> callCC (\c -> view _Wrapped (p (ReadFilePathT . pure . c)) r))
  {-# INLINE callCC #-}

instance MonadError e f => MonadError e (ReadFilePathT f) where
  throwError =
    lift . throwError
  {-# INLINE throwError #-}
  catchError (ReadFilePathT f) g =
    ReadFilePathT (\ r -> catchError (f r) (\ e -> view _Wrapped (g e) r))
  {-# INLINE catchError #-}

instance MonadPlus f => MonadPlus (ReadFilePathT f) where
  mzero =
    lift mzero
  {-# INLINE mzero #-}
  ReadFilePathT a `mplus` ReadFilePathT b =
    ReadFilePathT (\ r -> a r `mplus` b r)
  {-# INLINE mplus #-}

hoistReadFilePath ::
  Applicative f =>
  ReadFilePath a
  -> ReadFilePathT f a
hoistReadFilePath =
  hoist (pure . runIdentity)

liftReadFilePath ::
  Applicative f =>
  (FilePath -> a)
  -> ReadFilePathT f a
liftReadFilePath =
  hoistReadFilePath . (readFilePath #)