packages feed

reader-0.0.8: src/Data/Reader/Reader2.hs

{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE RankNTypes #-}

module Data.Reader.Reader2(
  Reader2T(..)
, Reader2
, Reader2Lens
, reader2
, reader2Lens
, reader2'
, star2
, kleisli2
, liftReader2
, pureReader2
, homReader2
) where

import Control.Applicative
    ( Applicative((<*>), pure), Alternative((<|>), empty) )
import Control.Arrow
    ( ArrowZero(..),
      ArrowPlus(..),
      Arrow(first, second, arr),
      (>>>),
      ArrowApply(..),
      ArrowChoice(..),
      ArrowLoop(..),
      Kleisli )
import Control.Category ( Category(..) )
import Control.Lens
    ( LensLike, view, iso, over, _Wrapped, Iso, Rewrapped, Wrapped(..) )
import Control.Monad
    ( Monad(return, (>>=)), sequence, MonadPlus(..), (>=>) )
import qualified Control.Monad.Reader as Reader( ReaderT )
import Control.Monad.Reader.Class ( MonadReader )
import qualified Control.Monad.Reader.Class as Reader ( MonadReader(..) )
import Control.Monad.State.Class ( MonadState(..) )
import Control.Monad.Writer.Class ( MonadWriter(..) )
import Control.Monad.Error.Class ( MonadError(..) )
import Control.Monad.Fix ( MonadFix(..) )
import Control.Monad.Cont.Class ( MonadCont(..) )
import Control.Monad.IO.Class ( MonadIO(..) )
import Data.Distributive ( Distributive(distribute, collect) )
import Data.Either ( Either(Right, Left), either )
import Data.Functor ( Functor(fmap) )
import Data.Functor.Alt ( Alt((<!>)) )
import Data.Functor.Apply ( Apply((<.>), liftF2) )
import Data.Functor.Bind ( Bind((>>-)), (->-) )
import Data.Functor.Contravariant ( Contravariant(contramap) )
import Data.Functor.Contravariant.Divisible
    ( Decidable(..), Divisible(..) )
import Data.Functor.Identity ( Identity(..) )
import Data.Functor.Plus ( Plus(..) )
import Data.Monoid(Monoid(mempty))
import Data.Profunctor
    ( Choice(..),
      Profunctor(dimap),
      Star,
      Closed(..),
      Costrong(unfirst),
      Strong(..),
      Mapping(..),
      Cochoice(unright) )
import Data.Profunctor.Traversing ( Traversing(..) )
import Data.Reader.Reader
    ( pureReader,
      homReader,
      reader,
      readerLens,
      star,
      kleisli,
      reader',
      liftReader )
import Data.Semigroup ( Semigroup((<>)) )
import Data.Semigroupoid ( Semigroupoid(..) )
import Data.Traversable ( Traversable(traverse) )
import Data.Tuple ( fst, snd, uncurry )

newtype Reader2T f a b =
  Reader2T (a -> f b)

instance Reader2T f a b ~ x =>
  Rewrapped (Reader2T f' a' b') x
instance Wrapped (Reader2T f a b) where
  type Unwrapped (Reader2T f a b) =
    a
    -> f b
  _Wrapped' =
    iso (\(Reader2T x) -> x) Reader2T

type Reader2 a b =
  Reader2T Identity a b

reader2 ::
  Iso
    (Reader2 a b)
    (Reader2 a' b')
    (a -> b)
    (a' -> b')
reader2 =
  reader

reader2' ::
  Iso
    (Reader.ReaderT a f b)
    (Reader.ReaderT a' f' b')
    (Reader2T f a b)
    (Reader2T f' a' b')
reader2' =
  reader'

type Reader2Lens f s t a b =
  Reader2T f a b
  -> Reader2T f s t

reader2Lens ::
  Iso
    (LensLike f s t a b)
    (LensLike f' s' t' a' b')
    (Reader2Lens f s t a b)
    (Reader2Lens f' s' t' a' b')
reader2Lens =
  readerLens

star2 ::
  Iso
    (Star f a b)
    (Star f' a' b')
    (Reader2T f a b)
    (Reader2T f' a' b')
star2 =
  star

kleisli2 ::
  Iso
    (Kleisli f a b)
    (Kleisli f' a' b')
    (Reader2T f a b)
    (Reader2T f' a' b')
kleisli2 =
  kleisli

liftReader2 ::
  Iso
    (Reader2T f a b)
    (Reader2T f' a' b')
    (Reader2 a (f b))
    (Reader2 a' (f' b'))
liftReader2 =
  liftReader

pureReader2 ::
  Applicative f =>
  Reader2 a b
  -> Reader2T f a b
pureReader2 =
  pureReader

homReader2 ::
  (forall x. f x -> g x)
  -> Reader2T f a b
  -> Reader2T g a b
homReader2 =
  homReader

instance Functor f => Functor (Reader2T f a) where
  fmap f (Reader2T g) =
    Reader2T (fmap (fmap f) g)

instance Apply f => Apply (Reader2T f a) where
  Reader2T f <.> Reader2T a =
    Reader2T (\x -> f x <.> a x)

instance Applicative f => Applicative (Reader2T f a) where
  pure =
    Reader2T . pure . pure
  Reader2T f <*> Reader2T a =
    Reader2T (\x -> f x <*> a x)

instance Bind f => Bind (Reader2T f a) where
  Reader2T a >>- f =
    Reader2T (\x -> a x >>- \l -> view _Wrapped (f l) x)

instance Monad f => Monad (Reader2T f a) where
  return =
    pure
  Reader2T a >>= f =
    Reader2T (\x -> a x >>= \l -> view _Wrapped (f l) x)

instance Alt f => Alt (Reader2T f a) where
  Reader2T x <!> Reader2T y =
    Reader2T (\a -> x a <!> y a)

instance Alternative f => Alternative (Reader2T f a) where
  Reader2T x <|> Reader2T y =
    Reader2T (\a -> x a <|> y a)
  empty =
    Reader2T (pure empty)

instance (Alt f, Alternative f) => Plus (Reader2T f a) where
  zero =
    empty

instance MonadPlus f => MonadPlus (Reader2T f a) where
  mzero =
    empty
  mplus =
    (<|>)

instance (Semigroup b, Apply f) => Semigroup (Reader2T f a b) where
  Reader2T x <> Reader2T y =
    Reader2T (\a -> liftF2 (<>) (x a) (y a))

instance (Monoid b, Apply f, Applicative f) => Monoid (Reader2T f a b) where
  mempty =
    Reader2T (pure (pure mempty))

instance Monad f => MonadReader a (Reader2T f a) where
  ask =
    Reader2T pure
  local f =
    over _Wrapped (. f)
  reader f =
    Reader2T (pure . f)

instance MonadWriter a f => MonadWriter a (Reader2T f a) where
  writer =
    Reader2T . pure . writer
  tell =
    Reader2T . pure . tell
  listen =
    over _Wrapped (listen .)
  pass =
    over _Wrapped (pass .)

instance MonadState a f => MonadState a (Reader2T f a) where
  get =
    (Reader2T . pure) get
  put =
    Reader2T . pure . put
  state =
    Reader2T . pure . state

instance MonadError a f => MonadError a (Reader2T f a) where
  throwError =
    Reader2T . pure . throwError
  catchError m h =
    Reader2T (\r -> catchError (view _Wrapped m r) (\e -> view _Wrapped (h e) r))

instance MonadCont f => MonadCont (Reader2T f a) where
  callCC f =
    Reader2T (\r -> callCC (\ c -> view _Wrapped (f (Reader2T . pure . c)) r))

instance MonadIO f => MonadIO (Reader2T f a) where
  liftIO =
    Reader2T . pure . liftIO

instance Functor f => Profunctor (Reader2T f) where
  dimap f g =
    over _Wrapped (\k -> fmap g . k . f)

instance Functor f => Strong (Reader2T f) where
  first' =
    over _Wrapped (\k (a, c) -> fmap (, c) (k a))
  second' =
    over _Wrapped (\k (c, a) -> fmap (c ,) (k a))

instance Applicative f => Choice (Reader2T f) where
  left' =
    over _Wrapped (\k -> either (fmap Left . k) (pure . Right))
  right' =
    over _Wrapped (\k -> either (pure . Left) (fmap Right . k))

instance Applicative f => Traversing (Reader2T f) where
  traverse' =
    over _Wrapped traverse
  wander =
    over _Wrapped

instance Distributive f => Closed (Reader2T f) where
  closed =
    over _Wrapped (\k x -> distribute (k . x))

instance (Applicative f, Distributive f) => Mapping (Reader2T f) where
  map' =
    over _Wrapped collect
  roam f =
    over _Wrapped (\k s -> fmap (`f` s) (distribute k))

instance MonadFix f => Costrong (Reader2T f) where
  unfirst =
    over _Wrapped (\f a -> fmap fst (mfix (\y -> f (a, snd y))))

instance Traversable f => Cochoice (Reader2T f) where
  unright =
    over _Wrapped (\f ->
      let go = either (go . Left) id . sequence . f
      in  go . Right)

instance Bind f => Semigroupoid (Reader2T f) where
  o (Reader2T f) (Reader2T g) =
    Reader2T (g ->- f)

instance Monad f => Category (Reader2T f) where
  Reader2T f . Reader2T g =
    Reader2T (g >=> f)
  id =
    Reader2T pure

instance Monad f => Arrow (Reader2T f) where
  arr f =
    Reader2T (pure . f)
  first =
    over _Wrapped (\f (b, d) -> fmap (, d) (f b))
  second =
    over _Wrapped (\f (d, b) -> fmap (d ,) (f b))

instance MonadFix f => ArrowLoop (Reader2T f) where
  loop =
    unfirst

instance Monad f => ArrowApply (Reader2T f) where
  app =
    Reader2T (uncurry (view _Wrapped))

instance Monad f => ArrowChoice (Reader2T f) where
  left f =
    f +++ arr id
  right f =
    arr id +++ f
  f +++ g =
    (f >>> arr Left) ||| (g >>> arr Right)
  Reader2T f ||| Reader2T g =
    Reader2T (either f g)

instance MonadPlus f => ArrowZero (Reader2T f) where
    zeroArrow = Reader2T (pure mzero)

instance MonadPlus f => ArrowPlus (Reader2T f) where
    Reader2T f <+> Reader2T g = Reader2T (\x -> f x `mplus` g x)

instance Contravariant f => Contravariant (Reader2T f a) where
  contramap f =
    over _Wrapped (fmap (contramap f))

instance Divisible f => Divisible (Reader2T f a) where
  divide k (Reader2T f) (Reader2T g) =
    Reader2T (liftF2 (divide k) f g)
  conquer =
    Reader2T (pure conquer)

instance Decidable f => Decidable (Reader2T f a) where
  lose =
    Reader2T . pure . lose
  choose k (Reader2T f) (Reader2T g) =
    Reader2T (liftF2 (choose k) f g)