Reputation: 513
I have a function that produces a Maybe a
type and I'm using it in a function to produce an Either b a
. Is there a way I can map Nothing
to Left x
to simplify my code? The following code gives some context:
rmX :: ... -> Maybe a
cvX :: ... -> Either CVXError a
data CVXError = BadIndex | NoCover | NoSpace
cvX ... =
...
case rmx 1 xs of
Nothing -> Left NoSpace
Just p -> Right (x2:x1:(fromJust (rmX (-1) p)))
-- given that rmX always passes on negative value arg
The case statement is just begging to be replaced with fmap
but the problem is that I'm not sure how to 'map' Nothing
to Left NoSpace
in an fmap
call or to even extract this pattern to make my own util function.
Upvotes: 2
Views: 223
Reputation: 531625
One similar option is to use the Maybe
monad until the very end, then apply Left
or Right
as necessary with maybe
.
maybe (Left NoSpace) Right $ do
p1 <- rmX 1 xs
p2 <- rmX (-1) p1
return (x2:x1:p2)
There's lots of room for tweaking this, depending on your preference for do
notation vs >>=
:
-- untested; take these with a grain of salt...
maybe (Left NoSpace) Right $ do
p <- rmX 1 xs >>= rmX (-1)
return (x2:x1:p)
maybe (Left NoSpace) Right (rmX 1 xs >>= rmX (-1) >>= (return . (x1:)) >>= (return . (x2:)))
-- etc
Upvotes: 0
Reputation: 34388
In this context, it is worth mentioning the errors package. It offers a number of functions for juggling Maybe
, Either
and related types, including note
, which "[tags] the Nothing
value of a Maybe
":
note :: a -> Maybe b -> Either a b
cvX ... =
...
note NoSpace $ fmap (\p -> x2:x1:(fromJust (rmX (-1) p))) (rmX 1 xs)
Unsurprisingly, the implementation of note
uses maybe
exactly like Sebastian Redl's answer does.
P.S.: It is always a little unpleasant to use fromJust
, given how it fails when given Nothing
. If rmX (-1)
cannot produce a Nothing
, you might want to consider factoring out a separate function that doesn't return Maybe a
to be used instead of fromJust (rmX (-1) p)
.
Upvotes: 4
Reputation: 72019
You're looking for the maybe
function:
cvX ... =
...
maybe (Left NoSpace) (\p -> Right (x2:x1:(fromJust (rmX (-1) p)))) $
rmX 1 xs
Upvotes: 6