Combining results from two Either Monads

Viewed 186

How do you handle this situation (pseudocode provided below) in Haskell?

 x = somethingThatReturnsMaybe(s1)
 y = somethingThatReturnsMaybe(s2)

 if(x == Nothing) return Left "invalid x"
 if(y == Nothing) return Left "invalid y"

 callFn(fromJust(x), fromJust(y));

I can think of two ways:-

  1. Pass Maybes from calling place, so that the above code can be wrapped in a function, and I can use pattern matching in the function binding/definition.
  2. I have written this code to combine these values using Either
mapToRight (\(x, y) -> callFn x y) combined_values
                where { combined_values = (maybeToRight "Invalid x!" x >>= combiner) <*>
                                        maybeToRight "Invalid target position" y;
                mapToRight = second; x = somethingThatReturnsMaybe s1; y = somethingThatReturnsMaybe s2
                }

For the second option I have following combinators

combiner :: b -> Either a (b0 -> (b, b0));
combiner x = Right (x,)

maybeToRight :: a -> Maybe b -> Either a b
maybeToRight a Nothing = Left a
maybeToRight a (Just x) = Right x

Is there any preference among these two (although the first one is less preferable to me because it might involve more changes), or is there any better option?

1 Answers

I would import Control.Error, then write this:

do
    x <- note "invalid x" (somethingThatReturnsMaybe s1)
    y <- note "invalid y" (somethingThatReturnsMaybe s2)
    callFn x y

The note here is your maybeToRight. The Either's implementation of (>>=) is handling the unwrapping/combining.

Related