Reputation: 85372
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
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
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
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
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