Sridhar Ratnakumar
Sridhar Ratnakumar

Reputation: 85372

Either and inner Maybe error handling

Is there a Haskell pattern that obviates the writing of this custom function? The idea being to handle the Nothing from Maybe as an error (as part of the wrapping Either):

eitherMaybeHandle :: String -> Either String (Maybe a) -> Either String a
eitherMaybeHandle err = \case
  Left e ->
    Left e
  Right Nothing ->
    Left err
  Right (Just a) ->
    Right a

Upvotes: 1

Views: 1756

Answers (4)

Daniel Wagner
Daniel Wagner

Reputation: 152837

I would use the errors package, which offers

note :: a -> Maybe b -> Either a b

which can be combined with another Either with the Monad instance:

eitherMaybeHandle :: e -> Either e (Maybe a) -> Either e a
eitherMaybeHandle err act = act >>= note err

Upvotes: 2

castletheperson
castletheperson

Reputation: 33476

First, you can use sequence to turn an Either a (Maybe b) into a Maybe (Either a b). Then you can apply fromMaybe to the result along with your value of type a in order to get an Either a b.

import Data.Maybe (fromMaybe)

eitherMaybeHandle :: a -> Either a (Maybe b) -> Either a b
eitherMaybeHandle err = fromMaybe (Left err) . sequence

Upvotes: 6

chi
chi

Reputation: 116139

The original code is already fine. You might want to consider making it occupy fewer lines by keeping each branch on the same line.

Otherwise, just for the sake of alternatives, you could use:

eitherMaybeHandle :: String -> Either String (Maybe a) -> Either String a
eitherMaybeHandle _   (Left e)         = Left e
eitherMaybeHandle err (Right Nothing)  = Left err
eitherMaybeHandle _   (Right (Just a)) = Right a

or even

eitherMaybeHandle :: String -> Either String (Maybe a) -> Either String a
eitherMaybeHandle _   (Left e)  = Left e
eitherMaybeHandle err (Right x) = maybe (Left err) Right x

I'd consider the original code to be more readable than the latter alternative.

Upvotes: 3

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476659

Perhaps not the most simpel function, but an attempt using monads and the Maybe catamorphism like:

import Data.Maybe(maybe)

eitherMaybeHandle :: a -> Either a (Maybe b) -> Either a b
eitherMaybeHandle err = (>>= maybe (Left err) Right)

We can even drop the err parameter, and write it like:

eitherMaybeHandle :: a -> Either a (Maybe b) -> Either a b
eitherMaybeHandle = (=<<) . flip maybe Right . Left

Since Either a is a monad instance, we can thus use >>=. In that case, we leave the Left x untouched, and the Right x is passed through the function.

As function we use maybe :: a -> (b -> a) -> Maybe b -> a. So we map Nothing on Left err, and we use Right as a function to transform Just x, in Right x.

Upvotes: 2

Related Questions