2

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.

3 Answers 3

6

You're looking for the maybe function:

cvX ... =
  ...
  maybe (Left NoSpace) (\p -> Right (x2:x1:(fromJust (rmX (-1) p)))) $
    rmX 1 xs
Sign up to request clarification or add additional context in comments.

Comments

4

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).

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.