packages feed

aztecs-0.14.0: src/Aztecs/ECS/Commands.hs

{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

module Aztecs.ECS.Commands where

import Aztecs.ECS.Query.Class
import Control.Monad.IO.Class
import Control.Monad.Primitive
import Control.Monad.Trans

newtype Commands t m a = Commands {unCommands :: m (a, t m ())}
  deriving (Functor)

instance (Monad (t m), Monad m) => Applicative (Commands t m) where
  pure x = Commands $ pure (x, pure ())
  {-# INLINE pure #-}
  Commands mf <*> Commands mx = Commands $ do
    (f, w1) <- mf
    (x, w2) <- mx
    return (f x, w1 >> w2)
  {-# INLINE (<*>) #-}

instance (Monad (t m), Monad m) => Monad (Commands t m) where
  Commands mx >>= f = Commands $ do
    (x, w1) <- mx
    (y, w2) <- unCommands (f x)
    return (y, w1 >> w2)
  {-# INLINE (>>=) #-}

instance (MonadTrans t) => MonadTrans (Commands t) where
  lift m = Commands $ do
    x <- m
    return (x, lift $ pure ())
  {-# INLINE lift #-}

instance (MonadTrans t, Monad (t m), MonadIO m) => MonadIO (Commands t m) where
  liftIO io = Commands $ do
    x <- liftIO io
    return (x, lift $ pure ())
  {-# INLINE liftIO #-}

instance (MonadTrans t, Monad (t m), PrimMonad m) => PrimMonad (Commands t m) where
  type PrimState (Commands t m) = PrimState m
  primitive f = Commands $ do
    x <- primitive f
    return (x, lift $ pure ())
  {-# INLINE primitive #-}

runCommands :: (MonadTrans t, Monad (t m), Monad m) => Commands t m a -> t m a
runCommands (Commands m) = do
  (result, action) <- lift m
  action
  return result
{-# INLINE runCommands #-}

queue :: (Applicative m) => t m () -> Commands t m ()
queue action = Commands $ pure ((), action)
{-# INLINE queue #-}