packages feed

reader-0.0.5: src/Data/Reader/Reader3.hs

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

module Data.Reader.Reader3(
  Reader3T(..)
, Reader3
, Reader3Lens
, reader3
, reader3Lens
, reader3'
, star3
, kleisli3
, liftReader3
, pureReader3
, homReader3
) where

import Control.Applicative
    ( Applicative(pure), liftA2 )
import Control.Arrow ( Kleisli )
import Control.Category ( Category(..) )
import Control.Lens
    ( LensLike, view, iso, review, over, _Wrapped, Iso, Rewrapped, Wrapped(..) )
import qualified Control.Monad.Reader as Reader(ReaderT(ReaderT))
import Data.Either ( either )
import Data.Functor.Apply ( Apply(liftF2) )
import Data.Functor.Contravariant ( Contravariant(contramap) )
import Data.Functor.Contravariant.Divisible
    ( Decidable(..), Divisible(..) )
import Data.Functor.Identity ( Identity(..) )
import Data.Profunctor ( Star )
import Data.Monoid(Monoid(mempty, mappend))
import Data.Reader.Reader
    ( pureReader, homReader, reader, readerLens, star, kleisli )
import Data.Semigroup ( Semigroup((<>)) )
import Data.Void ( absurd )

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

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

type Reader3 a b =
  Reader3T Identity b a

reader3 ::
  Iso
    (Reader3 a b)
    (Reader3 a' b')
    (a -> b)
    (a' -> b')
reader3 =
  reader

reader3' ::
  Iso
    (Reader.ReaderT a f b)
    (Reader.ReaderT a' f' b')
    (Reader3T f b a)
    (Reader3T f' b' a')
reader3' =
  iso
    (\(Reader.ReaderT k) -> Reader3T k)
    (\(Reader3T k) -> Reader.ReaderT k)

type Reader3Lens f s t a b =
  Reader3T f b a
  -> Reader3T f t s

reader3Lens ::
  Iso
    (LensLike f s t a b)
    (LensLike f' s' t' a' b')
    (Reader3Lens f s t a b)
    (Reader3Lens f' s' t' a' b')
reader3Lens =
  readerLens

star3 ::
  Iso
    (Star f a b)
    (Star f' a' b')
    (Reader3T f b a)
    (Reader3T f' b' a')
star3 =
  star

kleisli3 ::
  Iso
    (Kleisli f a b)
    (Kleisli f' a' b')
    (Reader3T f b a)
    (Reader3T f' b' a')
kleisli3 =
  kleisli

liftReader3 ::
  Iso
    (Reader3T f b a)
    (Reader3T f' b' a')
    (Reader3 a (f b))
    (Reader3 a' (f' b'))
liftReader3 =
  iso
    (review reader3 . view _Wrapped)
    (review _Wrapped . view reader3)

pureReader3 ::
  Applicative f =>
  Reader3 a b
  -> Reader3T f b a
pureReader3 =
  pureReader

homReader3 ::
  (forall x. f x -> g x)
  -> Reader3T f b a
  -> Reader3T g b a
homReader3 =
  homReader

instance Contravariant (Reader3T f b) where
  contramap f =
    over _Wrapped (. f)

instance (Monoid b, Applicative f) => Divisible (Reader3T f b) where
  conquer =
    Reader3T (pure (pure mempty))
  divide k (Reader3T f) (Reader3T g) =
    Reader3T (\a -> let (b, c) = k a in liftA2 mappend (f b) (g c))

instance (Monoid b, Applicative f) => Decidable (Reader3T f b) where
  lose f =
    Reader3T (absurd . f)
  choose k (Reader3T f) (Reader3T g) =
    Reader3T (either f g . k)

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

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