module Dovin.Monad where

import           Control.Monad.Identity
import           Control.Monad.Except
import           Control.Monad.Writer
import           Control.Monad.Reader
import           Control.Monad.State hiding (state)

import Dovin.Types

runMonad :: Board -> GameMonad a -> (Either String a, Board, [Step])
runMonad :: Board -> GameMonad a -> (Either String a, Board, [Step])
runMonad Board
state GameMonad a
m =
  let ((Either String a
e, Board
b), [Step]
log) = Identity ((Either String a, Board), [Step])
-> ((Either String a, Board), [Step])
forall a. Identity a -> a
runIdentity (Identity ((Either String a, Board), [Step])
 -> ((Either String a, Board), [Step]))
-> Identity ((Either String a, Board), [Step])
-> ((Either String a, Board), [Step])
forall a b. (a -> b) -> a -> b
$
                        WriterT [Step] Identity (Either String a, Board)
-> Identity ((Either String a, Board), [Step])
forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
runWriterT (StateT Board (WriterT [Step] Identity) (Either String a)
-> Board -> WriterT [Step] Identity (Either String a, Board)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT (ReaderT
  Env (StateT Board (WriterT [Step] Identity)) (Either String a)
-> Env -> StateT Board (WriterT [Step] Identity) (Either String a)
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (GameMonad a
-> ReaderT
     Env (StateT Board (WriterT [Step] Identity)) (Either String a)
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT GameMonad a
m) Env
emptyEnv) Board
state) in

  (Either String a
e, Board
b, [Step]
log)

execMonad :: Board -> GameMonad a -> Either String a
execMonad :: Board -> GameMonad a -> Either String a
execMonad Board
state GameMonad a
m =
  let result :: Either String a
result = (Either String a, [Step]) -> Either String a
forall a b. (a, b) -> a
fst ((Either String a, [Step]) -> Either String a)
-> (Either String a, [Step]) -> Either String a
forall a b. (a -> b) -> a -> b
$ Identity (Either String a, [Step]) -> (Either String a, [Step])
forall a. Identity a -> a
runIdentity (WriterT [Step] Identity (Either String a)
-> Identity (Either String a, [Step])
forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
runWriterT (StateT Board (WriterT [Step] Identity) (Either String a)
-> Board -> WriterT [Step] Identity (Either String a)
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT (ReaderT
  Env (StateT Board (WriterT [Step] Identity)) (Either String a)
-> Env -> StateT Board (WriterT [Step] Identity) (Either String a)
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (GameMonad a
-> ReaderT
     Env (StateT Board (WriterT [Step] Identity)) (Either String a)
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT GameMonad a
m) Env
emptyEnv) Board
state)) in

  Either String a
result