packages feed

functor-monad-0.1.1.0: src/FMonad/State/Lan.hs

{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DerivingVia #-}
module FMonad.State.Lan
  (StateT(..),
   fromAdjointT,
   toAdjointT,
   toInner, fromInner,
   
   State,
   state, runState
  ) where

import Control.Monad.Trans.Identity
import Data.Functor.Kan.Lan
import Data.Functor.Precompose
import qualified FMonad.State.Simple.Inner as Simple.Inner

import FMonad
import FMonad.Adjoint
import Data.Tuple (swap)
import Control.Monad.Trans.Writer (WriterT(..))
import Control.Comonad.Traced (TracedT(..))
import Data.Coerce (coerce)

-- type StateT s = AdjointT (Lan s) (Precompose s)
newtype StateT s mm x a = StateT { runStateT :: mm (Lan s x) (s a) }
  deriving (FFunctor, FMonad) via (AdjointT (Lan s) (Precompose s) mm)

deriving
  stock instance (FFunctor mm, Functor s) => Functor (StateT s mm x)

toAdjointT :: StateT s mm x ~> AdjointT (Lan s) (Precompose s) mm x
toAdjointT = coerce

fromAdjointT :: AdjointT (Lan s) (Precompose s) mm x ~> StateT s mm x
fromAdjointT = coerce

toInner :: (Functor x, FFunctor mm) => StateT ((,) s1) mm x ~> Simple.Inner.StateT s1 mm x
toInner = Simple.Inner.fromAdjointT . AdjointT . ffmap (ffmap lanToTraced) . (WriterT . fmap swap . getPrecompose) . runAdjointT . toAdjointT

fromInner :: (Functor x, FFunctor mm) => Simple.Inner.StateT s1 mm x ~> StateT ((,) s1) mm x
fromInner = fromAdjointT . AdjointT . ffmap (ffmap tracedToLan) . (Precompose . fmap swap . runWriterT) . runAdjointT . Simple.Inner.toAdjointT

lanToTraced :: Functor f => Lan ((,) s1) f ~> TracedT s1 f
lanToTraced (Lan sr_a fr) = TracedT $ fmap (\r s -> sr_a (s,r)) fr

tracedToLan :: TracedT s1 f ~> Lan ((,) s1) f
tracedToLan (TracedT fsa) = Lan (\(s1,sa) -> sa s1) fsa

-- * Pure state

type State s = StateT s IdentityT

state :: (Functor s, FMonad mm, Functor x)
  => (s b -> s a) -> x b -> StateT s mm x a
state f xb = StateT $ fpure (Lan f xb)

runState :: State s x a -> Lan s x (s a)
runState = runIdentityT . runStateT