-- |
-- Module:     Control.Wire.Prefab.Execute
-- Copyright:  (c) 2011 Ertugrul Soeylemez
-- License:    BSD3
-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
--
-- Monadic computations for wires over Kleisli arrows.  The difference
-- between these wires and 'Control.Wire.Classes.arrM' is that these are
-- exception-aware.

module Control.Wire.Prefab.Execute
    ( -- * Run monadic actions
      WExecute(..)
    )
    where

import Control.Applicative
import Control.Arrow
import Control.Exception.Lifted as Ex
import Control.Monad
import Control.Monad.Trans.Control
import Control.Wire.Types


-- | Run monadic actions.

class Arrow (>~) => WExecute m (>~) | (>~) -> m where
    -- | Run the input monadic action at each instant.
    --
    -- * Depends: Current instant.
    --
    -- * Inhibits: Whenever the input computation throws an exception.
    execute :: Applicative f => Wire (f SomeException) (>~) (m b) b
    execute = executeWith pure

    -- | Run the input monadic action at each instant.  The argument
    -- function converts thrown exceptions to inhibition values.
    --
    -- * Depends: Current instant.
    --
    -- * Inhibits: Whenever the input computation throws an exception.
    executeWith :: (SomeException -> e) -> Wire e (>~) (m b) b

instance MonadBaseControl IO m => WExecute m (Kleisli m) where
    executeWith fromEx =
        mkFixM $ liftM (either (Left . fromEx) Right) . Ex.try