------------------------------------------------------------------------
-- |
-- Module           : What4.Utils.MonadST
-- Description      : Typeclass for monads generalizing ST
-- Copyright        : (c) Galois, Inc 2014-2020
-- License          : BSD3
-- Maintainer       : Joe Hendrix <jhendrix@galois.com>
-- Stability        : provisional
--
-- This module defines the MonadST class, which contains the ST
-- and IO monads and a small collection of moand transformers over them.
------------------------------------------------------------------------


{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE UndecidableInstances #-}

module What4.Utils.MonadST
  ( MonadST(..)
  , Control.Monad.ST.ST
  , RealWorld
  ) where

import Control.Monad.ST
import Control.Monad.Cont
import Control.Monad.Reader
import Control.Monad.State as L
import Control.Monad.State.Strict as S
import Control.Monad.Writer as L
import Control.Monad.Writer.Strict as S

class Monad m => MonadST s m | m -> s where
  liftST :: ST s a -> m a

instance MonadST RealWorld IO where
  liftST :: ST RealWorld a -> IO a
liftST = ST RealWorld a -> IO a
forall a. ST RealWorld a -> IO a
stToIO

instance MonadST s (ST s) where
  liftST :: ST s a -> ST s a
liftST = ST s a -> ST s a
forall a. a -> a
id

instance MonadST s m => MonadST s (ContT r m) where
  liftST :: ST s a -> ContT r m a
liftST ST s a
m = m a -> ContT r m a
forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> ContT r m a) -> m a -> ContT r m a
forall a b. (a -> b) -> a -> b
$ ST s a -> m a
forall s (m :: Type -> Type) a. MonadST s m => ST s a -> m a
liftST ST s a
m

instance MonadST s m => MonadST s (ReaderT r m) where
  liftST :: ST s a -> ReaderT r m a
liftST ST s a
m = m a -> ReaderT r m a
forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> ReaderT r m a) -> m a -> ReaderT r m a
forall a b. (a -> b) -> a -> b
$ ST s a -> m a
forall s (m :: Type -> Type) a. MonadST s m => ST s a -> m a
liftST ST s a
m

instance MonadST s m => MonadST s (L.StateT u m) where
  liftST :: ST s a -> StateT u m a
liftST ST s a
m = m a -> StateT u m a
forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> StateT u m a) -> m a -> StateT u m a
forall a b. (a -> b) -> a -> b
$ ST s a -> m a
forall s (m :: Type -> Type) a. MonadST s m => ST s a -> m a
liftST ST s a
m

instance MonadST s m => MonadST s (S.StateT u m) where
  liftST :: ST s a -> StateT u m a
liftST ST s a
m = m a -> StateT u m a
forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> StateT u m a) -> m a -> StateT u m a
forall a b. (a -> b) -> a -> b
$ ST s a -> m a
forall s (m :: Type -> Type) a. MonadST s m => ST s a -> m a
liftST ST s a
m

instance (MonadST s m, Monoid w) => MonadST s (L.WriterT w m) where
  liftST :: ST s a -> WriterT w m a
liftST ST s a
m = m a -> WriterT w m a
forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> WriterT w m a) -> m a -> WriterT w m a
forall a b. (a -> b) -> a -> b
$ ST s a -> m a
forall s (m :: Type -> Type) a. MonadST s m => ST s a -> m a
liftST ST s a
m

instance (MonadST s m, Monoid w) => MonadST s (S.WriterT w m) where
  liftST :: ST s a -> WriterT w m a
liftST ST s a
m = m a -> WriterT w m a
forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> WriterT w m a) -> m a -> WriterT w m a
forall a b. (a -> b) -> a -> b
$ ST s a -> m a
forall s (m :: Type -> Type) a. MonadST s m => ST s a -> m a
liftST ST s a
m