To simplify error handling without littering the code with arrowheads like
nonconsuming choice Foo : Either Text ()
controller Bar
do
case foo of
Left err -> pure $ Left err
Right x ->
-- do something
case bar of
Left err -> pure $ Left err
Right y ->
-- do something else
I have created an EitherT
monad transformer to hide some of the clutter with the Left
branches.
newtype EitherT m a b = EitherT { runEitherT : m (Either a b) }
instance Functor m => Functor (EitherT m a) where
fmap f = EitherT . fmap (fmap f) . runEitherT
instance Action m => Applicative (EitherT m a) where
pure = EitherT . pure . pure
EitherT meF <*> EitherT meX = EitherT $ do
eF <- meF
case eF of
Left err -> return (Left err)
Right f -> do
eX <- meX
case eX of
Left err -> return (Left err)
Right x -> return $ Right (f x)
instance Action m => Action (EitherT m a) where
EitherT meX >>= f = EitherT $ do
eX <- meX
case eX of
Left err -> return (Left err)
Right x -> runEitherT (f x)
However, this doesn’t seem to work in choices as this gives me a compile error:
nonconsuming choice Foo : Either Text ()
controller Bar
do
let lookupOptUpdate = lookupByKey @MyTemplate myKey
lookupEitherUpdate = fmap (optionalToEither "some text") lookupOptUpdate
lookupEitherT = EitherT lookupEitherUpdate
lookup <- lookupEitherT -- Compile error
With the message:
Couldn't match type ‘EitherT Update Text’ with ‘Update’
Expected type: Update (ContractId MyTemplate)
Actual type: EitherT Update Text (ContractId MyTemplate)
Am I doing something wrong?