{-# LANGUAGE FlexibleContexts #-}

-- |
-- Module     : Simulation.Aivika.Trans.Comp
-- Copyright  : Copyright (c) 2009-2014, David Sorokin <david.sorokin@gmail.com>
-- License    : BSD3
-- Maintainer : David Sorokin <david.sorokin@gmail.com>
-- Stability  : experimental
-- Tested with: GHC 7.8.3
-- It defines a type class of monads based on which the simulation monads can be built.
module Simulation.Aivika.Trans.Comp
        MonadCompTrans(..)) where

import Control.Monad
import Control.Monad.Trans

import Simulation.Aivika.Trans.Exception
import Simulation.Aivika.Trans.Session
import Simulation.Aivika.Trans.ProtoRef
import Simulation.Aivika.Trans.ProtoArray
import Simulation.Aivika.Trans.Unboxed
import Simulation.Aivika.Trans.Generator
import Simulation.Aivika.Trans.Internal.Specs

-- | A prototype of the type class of monads based on which the simulation monads can be built. 
class (Monad m,
       ExceptionHandling m,
       SessionMonad m,
       ProtoRefMonad m,
       ProtoArrayMonad m,
       Unboxed m Double,
       Unboxed m Float,
       Unboxed m Int,
       GeneratorMonad m) => ProtoMonadComp m

-- | Such a prototype monad that allows enqueueing events.
class (ProtoMonadComp m, EventQueueing m) => MonadComp m

-- | A variant of the standard 'MonadTrans' type class with one difference:
-- the computation that will be lifted into another must be 'MonadComp' instead of
-- more general and less restricted 'Monad'.
class MonadCompTrans t where

  -- | Lift the underlying computation into another within simulation.
  liftComp :: MonadComp m => m a -> t m a

instance ProtoMonadComp IO