\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

-- essenceoflivecoding
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 m a b e where
  Return :: e -> CellExcept m a b e
  Bind
    :: CellExcept m a b e1
    -> (e1 -> CellExcept m a b e2)
    -> CellExcept m a b e2
  Try
    :: (Data e, Finite e)
    => Cell (ExceptT e m) a b
    -> CellExcept m a b e
\end{code}

\begin{comment}
\begin{code}
instance Monad m => Functor (CellExcept m a b) where
  fmap :: (a -> b) -> CellExcept m a b a -> CellExcept m a b b
fmap = (a -> b) -> CellExcept m a b a -> CellExcept m a b b
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM

instance Monad m => Applicative (CellExcept m a b) where
  pure :: a -> CellExcept m a b a
pure = a -> CellExcept m a b a
forall (m :: * -> *) a. Monad m => a -> m a
return
  <*> :: CellExcept m a b (a -> b)
-> CellExcept m a b a -> CellExcept m a b b
(<*>) = CellExcept m a b (a -> b)
-> CellExcept m a b a -> CellExcept m a b b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
\end{code}
\end{comment}
The \mintinline{haskell}{Monad} instance is now trivial:
\begin{code}
instance Monad m => Monad (CellExcept m a b) where
  return :: a -> CellExcept m a b a
return = a -> CellExcept m a b a
forall e (m :: * -> *) a b. e -> CellExcept m a b e
Return
  >>= :: CellExcept m a b a
-> (a -> CellExcept m a b b) -> CellExcept m a b b
(>>=) = CellExcept m a b a
-> (a -> CellExcept m a b b) -> CellExcept m a b b
forall (m :: * -> *) a b e1 e2.
CellExcept m a b e1
-> (e1 -> CellExcept m a b e2) -> CellExcept m a b e2
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      m  a b 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 :: CellExcept m a b e -> Cell (ExceptT e m) a b
runCellExcept (Return e
e) = ExceptT e m b -> Cell (ExceptT e m) a b
forall (m :: * -> *) b a. m b -> Cell m a b
constM (ExceptT e m b -> Cell (ExceptT e m) a b)
-> ExceptT e m b -> Cell (ExceptT e m) a b
forall a b. (a -> b) -> a -> b
$ e -> ExceptT e m b
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE e
e
runCellExcept (Try Cell (ExceptT e m) a b
cell) = Cell (ExceptT e m) a b
cell
runCellExcept (Bind (Try Cell (ExceptT e1 m) a b
cell) e1 -> CellExcept m a b e
g) = Cell (ExceptT e1 m) a b
cell Cell (ExceptT e1 m) a b
-> Cell (ReaderT e1 (ExceptT e m)) a b -> Cell (ExceptT e m) a b
forall e1 (m :: * -> *) a b e2.
(Data e1, Monad m) =>
Cell (ExceptT e1 m) a b
-> Cell (ReaderT e1 (ExceptT e2 m)) a b -> Cell (ExceptT e2 m) a b
>>>== (e1 -> Cell (ExceptT e m) a b)
-> Cell (ReaderT e1 (ExceptT e m)) a b
forall e (m :: * -> *) a b.
(Finite e, Monad m) =>
(e -> Cell m a b) -> Cell (ReaderT e m) a b
commute (CellExcept m a b e -> Cell (ExceptT e m) a b
forall (m :: * -> *) a b e.
Monad m =>
CellExcept m a b e -> Cell (ExceptT e m) a b
runCellExcept (CellExcept m a b e -> Cell (ExceptT e m) a b)
-> (e1 -> CellExcept m a b e) -> e1 -> Cell (ExceptT e m) a b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e1 -> CellExcept m a b e
g)
runCellExcept (Bind (Return e1
e) e1 -> CellExcept m a b e
f) = CellExcept m a b e -> Cell (ExceptT e m) a b
forall (m :: * -> *) a b e.
Monad m =>
CellExcept m a b e -> Cell (ExceptT e m) a b
runCellExcept (CellExcept m a b e -> Cell (ExceptT e m) a b)
-> CellExcept m a b e -> Cell (ExceptT e m) a b
forall a b. (a -> b) -> a -> b
$ e1 -> CellExcept m a b e
f e1
e
runCellExcept (Bind (Bind CellExcept m a b e1
ce e1 -> CellExcept m a b e1
f) e1 -> CellExcept m a b e
g) = CellExcept m a b e -> Cell (ExceptT e m) a b
forall (m :: * -> *) a b e.
Monad m =>
CellExcept m a b e -> Cell (ExceptT e m) a b
runCellExcept (CellExcept m a b e -> Cell (ExceptT e m) a b)
-> CellExcept m a b e -> Cell (ExceptT e m) a b
forall a b. (a -> b) -> a -> b
$ CellExcept m a b e1
-> (e1 -> CellExcept m a b e) -> CellExcept m a b e
forall (m :: * -> *) a b e1 e2.
CellExcept m a b e1
-> (e1 -> CellExcept m a b e2) -> CellExcept m a b e2
Bind CellExcept m a b e1
ce ((e1 -> CellExcept m a b e) -> CellExcept m a b e)
-> (e1 -> CellExcept m a b e) -> CellExcept m a b e
forall a b. (a -> b) -> a -> b
$ \e1
e -> CellExcept m a b e1
-> (e1 -> CellExcept m a b e) -> CellExcept m a b e
forall (m :: * -> *) a b e1 e2.
CellExcept m a b e1
-> (e1 -> CellExcept m a b e2) -> CellExcept m a b e2
Bind (e1 -> CellExcept m a b e1
f e1
e) e1 -> CellExcept m a b 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 m a b e
try :: Cell (ExceptT e m) a b -> CellExcept m a b e
try = Cell (ExceptT e m) a b -> CellExcept m a b e
forall e (m :: * -> *) a b.
(Data e, Finite e) =>
Cell (ExceptT e m) a b -> CellExcept m a b e
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 m a b Void
  -> Cell       m a b
safely :: CellExcept m a b Void -> Cell m a b
safely = (forall x. ExceptT Void m x -> m x)
-> Cell (ExceptT Void m) a b -> Cell m a b
forall (m1 :: * -> *) (m2 :: * -> *) a b.
(forall x. m1 x -> m2 x) -> Cell m1 a b -> Cell m2 a b
hoistCell forall x. ExceptT Void m x -> m x
forall (m :: * -> *) a. Functor m => ExceptT Void m a -> m a
discardVoid (Cell (ExceptT Void m) a b -> Cell m a b)
-> (CellExcept m a b Void -> Cell (ExceptT Void m) a b)
-> CellExcept m a b Void
-> Cell m a b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CellExcept m a b Void -> Cell (ExceptT Void m) a b
forall (m :: * -> *) a b e.
Monad m =>
CellExcept m a b e -> Cell (ExceptT e m) a b
runCellExcept
discardVoid
  :: Functor      m
  => ExceptT Void m a
  ->              m a
discardVoid :: ExceptT Void m a -> m a
discardVoid
  = (Either Void a -> a) -> m (Either Void a) -> m a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Void -> a) -> (a -> a) -> Either Void a -> a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Void -> a
forall a. Void -> a
absurd a -> a
forall a. a -> a
id) (m (Either Void a) -> m a)
-> (ExceptT Void m a -> m (Either Void a))
-> ExceptT Void m a
-> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExceptT Void m a -> m (Either Void a)
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT
safe :: Monad m => Cell m a b -> CellExcept m a b Void
safe :: Cell m a b -> CellExcept m a b Void
safe Cell m a b
cell = Cell (ExceptT Void m) a b -> CellExcept m a b Void
forall e (m :: * -> *) a b.
(Data e, Finite e) =>
Cell (ExceptT e m) a b -> CellExcept m a b e
try (Cell (ExceptT Void m) a b -> CellExcept m a b Void)
-> Cell (ExceptT Void m) a b -> CellExcept m a b Void
forall a b. (a -> b) -> a -> b
$ Cell m a b -> Cell (ExceptT Void m) a b
forall (m :: * -> *) (t :: (* -> *) -> * -> *) a b.
(Monad m, MonadTrans t) =>
Cell m a b -> Cell (t m) a b
liftCell Cell m a b
cell
\end{code}
\end{comment}