content: \begin{comment}
  \begin{code}
  {-# LANGUAGE GADTs #-}
  
  module LiveCoding.CellExcept where
  
  -- base
  import Control.Monad
  import Data.Data
  import Data.Void
  
  -- transformers
  import Control.Monad.Trans.Except
  
  -- mmorph
  import Control.Monad.Morph
  
  -- essence-of-live-coding
  import LiveCoding.Cell
  import LiveCoding.Exceptions
  import LiveCoding.Exceptions.Finite
  \end{code}
  \end{comment}
  
  We can save on boiler plate by dropping the Coyoneda embedding for an ``operational'' monad:
  \fxerror{Cite operational}
  \fxerror{Move the following code into appendix?}
  \begin{code}
  data CellExcept a b m e where
    Return :: e -> CellExcept a b m e
    Bind
      :: CellExcept a b m e1
      -> (e1 -> CellExcept a b m e2)
      -> CellExcept a b m e2
    Try
      :: (Data e, Finite e)
      => Cell (ExceptT e m) a b
      -> CellExcept a b m e
  \end{code}
  
  \begin{comment}
  \begin{code}
  instance Monad m => Functor (CellExcept a b m) where
    fmap = liftM
  
  instance Monad m => Applicative (CellExcept a b m) where
    pure = return
    (<*>) = ap
  
  instance MFunctor (CellExcept a b) where
    hoist morphism (Return e) = Return e
    hoist morphism (Bind action cont) = Bind
      (hoist morphism action)
      (hoist morphism . cont)
    hoist morphism (Try cell) = Try $ hoistCell (mapExceptT morphism) cell
  \end{code}
  \end{comment}
  The \mintinline{haskell}{Monad} instance is now trivial:
  \begin{code}
  instance Monad m => Monad (CellExcept a b m) where
    return = Return
    (>>=) = Bind
  \end{code}
  As is typical for operational monads, all of the effort now goes into the interpretation function:
  \begin{code}
  runCellExcept
    :: Monad m
    => CellExcept a b m e
    -> Cell (ExceptT e m) a b
  \end{code}
  \begin{spec}
  runCellExcept (Bind (Try cell) g)
    = cell >>>= commute (runCellExcept . g)
  runCellExcept ... = ...
  \end{spec}
  \begin{comment}
  \begin{code}
  runCellExcept (Return e) = constM $ throwE e
  runCellExcept (Try cell) = cell
  runCellExcept (Bind (Try cell) g) = cell >>>== commute (runCellExcept . g)
  runCellExcept (Bind (Return e) f) = runCellExcept $ f e
  runCellExcept (Bind (Bind ce f) g) = runCellExcept $ Bind ce $ \e -> Bind (f e) g
  \end{code}
  \end{comment}
  
  As a slight restriction of the framework,
  throwing exceptions is now only allowed for finite types:
  \begin{code}
  try
    :: (Data e, Finite e)
    => Cell (ExceptT e m) a b
    -> CellExcept a b m e
  try = Try
  \end{code}
  In practice however, this is less often a limitation than first assumed,
  since in the monad context,
  calculations with all types are allowed again.
  \fxerror{But the trouble remains that builtin types like Int and Double can't be thrown.}
  
  \fxfatal{The rest is explained in the main article differently. Merge.}
  \begin{comment}
  \begin{code}
  safely
    :: Monad      m
    => CellExcept a b m Void
    -> Cell       m a b
  safely = hoistCell discardVoid . runCellExcept
  discardVoid
    :: Functor      m
    => ExceptT Void m a
    ->              m a
  discardVoid
    = fmap (either absurd id) . runExceptT
  safe :: Monad m => Cell m a b -> CellExcept a b m Void
  safe cell = try $ liftCell cell
  
  -- | Run a monadic action and immediately raise its result as an exception.
  once :: (Monad m, Data e, Finite e) => (a -> m e) -> CellExcept a arbitrary m e
  once kleisli = try $ arrM $ ExceptT . (Left <$>) . kleisli
  
  -- | Like 'once', but the action does not have an input.
  once_ :: (Monad m, Data e, Finite e) => m e -> CellExcept a arbitrary m e
  once_ = once . const
  \end{code}
  \end{comment}
  