Search code examples
haskellmonadseither

Monadic function of `(a -> m (Either e b)) -> Either e a -> m (Either e b)`?


Is there a way to write this function in a more "monadic" way, instead of resorting to pattern matching on Either?

{-# LANGUAGE LambdaCase #-}

calculate :: (Monad m) => (a -> m (Either e b)) -> Either e a -> m (Either e b)
calculate f = \case
  Left err   -> return $ Left err
  Right vals -> f vals

Specifically, for my use case, m is IO; f is a function that takes in input and produces some IO effect or fails, and the input is something that could have failed already.

Maybe using ExceptT?


Solution

  • Yep, looks like ExceptT to me. Though I would probably not use a function with this signature -- instead, I would use ExceptT more broadly, and then this function is just (=<<). Of course this is guesswork based on the use case.

    But if you must:

    calculate :: (Monad m) => (a -> m (Either e b)) -> Either e a -> m (Either e b)
    calculate f m = runExceptT (ExceptT . f =<< ExceptT m)