{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
module Control.Monad.Action where
import Control.Monad (join)
import Data.Constraint (Dict (..))
import Data.Functor.Const (Const (..))
import Control.Algebra.Free
( AlgebraType0
, AlgebraType
, FreeAlgebra1 (..)
, Proof (..)
)
import Data.Algebra.Pointed (Pointed (point))
import Data.Algebra.Free (FreeAlgebra, foldFree)
class (Monad m, Functor f) => MAction m f where
mact :: m (f a) -> f a
instance Monad m => MAction m m where
mact = join
instance (Pointed r, Functor f) => MAction ((->) r) f where
mact f = f point
instance ( Monad m
, FreeAlgebra m
, AlgebraType m d
)
=> MAction m (Const d) where
mact mca = Const $ foldFree $ getConst <$> mca
newtype FreeMAction m f a = FreeMAction { runFreeMAction :: m (f a) }
deriving (Show, Eq, Ord, Functor)
instance (Monad m, Functor f) => MAction m (FreeMAction m f) where
mact mfa = FreeMAction $ join $ runFreeMAction <$> mfa
type instance AlgebraType (FreeMAction m) f = MAction m f
type instance AlgebraType0 (FreeMAction m) f = Functor f
instance Monad m => FreeAlgebra1 (FreeMAction m) where
liftFree = FreeMAction . return
foldNatFree nat (FreeMAction mfa) = mact $ nat <$> mfa
proof1 = Proof Dict
forget1 = Proof Dict