packages feed

reader-0.0.7: 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
) where

import Control.Applicative
    ( Applicative(pure), liftA2 )
import Control.Category ( Category(..) )
import Control.Lens
    ( iso, over, _Wrapped, Rewrapped, Wrapped(..) )
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.Monoid(Monoid(mempty, mappend))
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

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))