{-# OPTIONS_GHC -Wall #-}
{-# OPTIONS_GHC -Wno-dodgy-exports #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Control.Monad.State.Profunctor.Class(
  IxFunctor(..)
, IxApply(..)
, IxApplicative(..)
, IxBind (..)
, IxMonad(..)
, IxAlt(..)
, IxAlternative(..)
, IxMonadState(..)
, IxMonadFix(..)
, IxMonadCont(..)
, IxBindTrans(..)
, IxMonadTrans(..)
) where

import Control.Applicative ( Applicative(pure) )
import Control.Monad ( Monad )
import Data.Functor.Bind ( Bind )

class IxFunctor f where
  ($.$) ::
    (a -> b)
    -> f j k a
    -> f j k b

infixl 4 $.$

class IxFunctor f => IxApply f where
  (<*.*>) ::
    f j k (a -> b)
    -> f i j a
    -> f i k b

infixl 4 <*.*>

class IxApply f => IxApplicative f where
  ipure ::
    a
    -> f i i a

class IxApply f => IxBind f where
  (-<<<) ::
    (a -> f i j b)
    -> f j k a
    -> f i k b
  a -> f i j b
f -<<< f j k a
g =
    f j k a
g f j k a -> (a -> f i j b) -> f i k b
forall j k a i b. f j k a -> (a -> f i j b) -> f i k b
forall (f :: * -> * -> * -> *) j k a i b.
IxBind f =>
f j k a -> (a -> f i j b) -> f i k b
>>>- a -> f i j b
f
  (>>>-) ::
    f j k a
    -> (a -> f i j b)
    -> f i k b
  f j k a
f >>>- a -> f i j b
g =
    a -> f i j b
g (a -> f i j b) -> f j k a -> f i k b
forall a i j b k. (a -> f i j b) -> f j k a -> f i k b
forall (f :: * -> * -> * -> *) a i j b k.
IxBind f =>
(a -> f i j b) -> f j k a -> f i k b
-<<< f j k a
f
  {-# MINIMAL (-<<<) | (>>>-) #-}

infixr 1 -<<<
infixr 1 >>>-

class (IxApplicative f, IxBind f) => IxMonad f where

class IxFunctor f => IxAlt f where
  (<|.|>) ::
    f i j a
    -> f i j a
    -> f i j a

infixl 3 <|.|>

class IxAlt f => IxAlternative f where
  iempty ::
    f i j a

class IxMonad f => IxMonadState f where
  iget ::
    f t t t
  iget =
    (t -> (t, t)) -> f t t t
forall s a t. (s -> (a, t)) -> f t s a
forall (f :: * -> * -> * -> *) s a t.
IxMonadState f =>
(s -> (a, t)) -> f t s a
istate (\t
s -> (t
s, t
s))
  iput ::
    t
    -> f t s ()
  iput t
s =
    (s -> ((), t)) -> f t s ()
forall s a t. (s -> (a, t)) -> f t s a
forall (f :: * -> * -> * -> *) s a t.
IxMonadState f =>
(s -> (a, t)) -> f t s a
istate (((), t) -> s -> ((), t)
forall a. a -> s -> a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((), t
s))
  istate ::
    (s -> (a, t))
    -> f t s a
  istate s -> (a, t)
f =
    f s s s
forall t. f t t t
forall (f :: * -> * -> * -> *) t. IxMonadState f => f t t t
iget f s s s -> (s -> f t s a) -> f t s a
forall j k a i b. f j k a -> (a -> f i j b) -> f i k b
forall (f :: * -> * -> * -> *) j k a i b.
IxBind f =>
f j k a -> (a -> f i j b) -> f i k b
>>>- \s
t ->
    let ~(a
a, t
s') = s -> (a, t)
f s
t
    in t -> f t s ()
forall t s. t -> f t s ()
forall (f :: * -> * -> * -> *) t s. IxMonadState f => t -> f t s ()
iput t
s' f t s () -> (() -> f t t a) -> f t s a
forall j k a i b. f j k a -> (a -> f i j b) -> f i k b
forall (f :: * -> * -> * -> *) j k a i b.
IxBind f =>
f j k a -> (a -> f i j b) -> f i k b
>>>-
    f t t a -> () -> f t t a
forall a. a -> () -> a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a -> f t t a
forall a i. a -> f i i a
forall (f :: * -> * -> * -> *) a i. IxApplicative f => a -> f i i a
ipure a
a)
  imodify ::
    (s -> t)
    -> f t s ()
  imodify s -> t
f =
    (s -> ((), t)) -> f t s ()
forall s a t. (s -> (a, t)) -> f t s a
forall (f :: * -> * -> * -> *) s a t.
IxMonadState f =>
(s -> (a, t)) -> f t s a
istate (\s
s -> ((), s -> t
f s
s))
  igets ::
    (s -> t)
    -> f s s t
  igets s -> t
f =
    s -> t
f (s -> t) -> f s s s -> f s s t
forall a b j k. (a -> b) -> f j k a -> f j k b
forall (f :: * -> * -> * -> *) a b j k.
IxFunctor f =>
(a -> b) -> f j k a -> f j k b
$.$ f s s s
forall t. f t t t
forall (f :: * -> * -> * -> *) t. IxMonadState f => f t t t
iget
  {-# MINIMAL istate | iget, iput #-}

class IxMonadFix f where
  imfix ::
    (a -> f t s a)
    -> f t s a

class IxMonadCont f where
  icallCC ::
    ((a -> f t r b) -> f r s a)
    -> f r s a

class IxBindTrans g where
  iliftB ::
    Bind f =>
    f a
    -> g f s s a

class IxMonadTrans g where
  ilift ::
    Monad f =>
    f a
    -> g f s s a