
Since I started into Haskell, I frequently run into a scenario like this: some function returns a Maybe value. If it is a Nothing, I want to do one thing, but if it isn't, I want to do something with the value encapsulated by the Maybe. But before I can use that value (say, to print it) I've got to pull it out of the Maybe in a way that satisfies the compiler. So one option is to use a separate function with pattern matching, for example: handleMaybeVal Nothing = do someAction someOtherActionEtc handleMaybeVal (Just a) = putStrLn ("The string in reverse is " ++ (reverse a)) Or I can use the maybe function with a conditional main = do val <- someIOFunc -- val is a Maybe String if val == Nothing then do someAction someOtherActionEtc else putStrLn ("The string in reverse is " ++ ((reverse . unpack) val)) where unpack a = maybe (error "unreachable error") (\b -> b) a The second option I like better, for some reason, but it is a bit dangerous, as I have to double check my code to make sure the default value passed to "maybe" cannot possibly be evaluated. (Alternatively, I could pass in a regular default value, like a blank string, though that is actually more dangerous in my mind because a bad value might be used silently.) Anyway: how do you pros go about handling situations like these? -- frigidcode.com theologia.indicium.us

Christopher Howard wrote:
Since I started into Haskell, I frequently run into a scenario like this: some function returns a Maybe value. If it is a Nothing, I want to do one thing, but if it isn't, I want to do something with the value encapsulated by the Maybe. But before I can use that value (say, to print it) I've got to pull it out of the Maybe in a way that satisfies the compiler. So one option is to use a separate function with pattern matching, for example:
handleMaybeVal Nothing = do someAction someOtherActionEtc handleMaybeVal (Just a) = putStrLn ("The string in reverse is " ++ (reverse a))
Or I can use the maybe function with a conditional
main = do val <- someIOFunc -- val is a Maybe String if val == Nothing then do someAction someOtherActionEtc else putStrLn ("The string in reverse is " ++ ((reverse . unpack) val)) where unpack a = maybe (error "unreachable error") (\b -> b) a
The second option I like better, for some reason, but it is a bit dangerous, as I have to double check my code to make sure the default value passed to "maybe" cannot possibly be evaluated. (Alternatively, I could pass in a regular default value, like a blank string, though that is actually more dangerous in my mind because a bad value might be used silently.)
Anyway: how do you pros go about handling situations like these?
I usually prefer an explicit pattern match like this: main = do val <- someIOFunc -- val is a Maybe String case val of Nothing -> do someAction someOtherActionEtc Just s -> putStrLn ("The string in reverse is " ++ (reverse s)) HTH, Erik -- ---------------------------------------------------------------------- Erik de Castro Lopo http://www.mega-nerd.com/

Your second option may or may not be dangerous, but it sure looks tricky. I wouldn't use 'maybe' that way. How about this? main = do val <- someIOFunc -- val is a Maybe String maybe (someAction >> someOtherActionEtc) (\theValue -> putStrLn ("the string in reverse is " ++ (reverse theValue)) val If you like point-free definitions: main = do val <- someIOFunc -- val is a Maybe String maybe (someAction >> someOtherActionEtc) (putStrLn . ("the string in reverse is " ++) . reverse) val The difference is that my use of 'maybe' involves giving it actions, and not just pure functions. On Tue, 2011-05-24 at 19:09 -0800, Christopher Howard wrote:
Since I started into Haskell, I frequently run into a scenario like this: some function returns a Maybe value. If it is a Nothing, I want to do one thing, but if it isn't, I want to do something with the value encapsulated by the Maybe. But before I can use that value (say, to print it) I've got to pull it out of the Maybe in a way that satisfies the compiler. So one option is to use a separate function with pattern matching, for example:
handleMaybeVal Nothing = do someAction someOtherActionEtc handleMaybeVal (Just a) = putStrLn ("The string in reverse is " ++ (reverse a))
Or I can use the maybe function with a conditional
main = do val <- someIOFunc -- val is a Maybe String if val == Nothing then do someAction someOtherActionEtc else putStrLn ("The string in reverse is " ++ ((reverse . unpack) val)) where unpack a = maybe (error "unreachable error") (\b -> b) a
The second option I like better, for some reason, but it is a bit dangerous, as I have to double check my code to make sure the default value passed to "maybe" cannot possibly be evaluated. (Alternatively, I could pass in a regular default value, like a blank string, though that is actually more dangerous in my mind because a bad value might be used silently.)
Anyway: how do you pros go about handling situations like these?

On Wednesday 25 May 2011 05:21:51, Elvio Toccalino wrote:
Your second option may or may not be dangerous, but it sure looks tricky. I wouldn't use 'maybe' that way. How about this?
main = do val <- someIOFunc -- val is a Maybe String maybe (someAction >> someOtherActionEtc) (\theValue -> putStrLn ("the string in reverse is " ++ (reverse theValue)) val
If you like point-free definitions:
main = do val <- someIOFunc -- val is a Maybe String maybe (someAction >> someOtherActionEtc) (putStrLn . ("the string in reverse is " ++) . reverse) val
The difference is that my use of 'maybe' involves giving it actions, and not just pure functions.
I'd do that (perhaps in the form someIOFunc >>= maybe ... ...) or pattern- match like Erik suggested. I prefer not to pass long arguments to maybe, so if there's much to do with someIOFunc's result, either name the branches and use maybe nothingBranch justBranch val or pattern-match case val of Nothing -> do something more ... Just v -> do foo v w <- bar v baz (a bit more below)
On Tue, 2011-05-24 at 19:09 -0800, Christopher Howard wrote:
Since I started into Haskell, I frequently run into a scenario like this: some function returns a Maybe value. If it is a Nothing, I want to do one thing, but if it isn't, I want to do something with the value encapsulated by the Maybe. But before I can use that value (say, to print it) I've got to pull it out of the Maybe in a way that satisfies the compiler. So one option is to use a separate function with pattern matching, for example:
handleMaybeVal Nothing = do someAction
someOtherActionEtc
handleMaybeVal (Just a) = putStrLn ("The string in reverse is " ++
(reverse a))
Or I can use the maybe function with a conditional
main = do val <- someIOFunc -- val is a Maybe String
if val == Nothing
This introduces an Eq constraint, so you can't use that if someIOFunc produces functions (or anything else without an Eq instance). The case pattern-matching avoids that constraint, and it does the unpacking in the same go too.
then do someAction
someOtherActionEtc
else putStrLn ("The string in reverse is " ++
((reverse . unpack) val))
where unpack a = maybe
(error "unreachable error") (\b -> b) a
That is unpack = maybe (error "unrechable error") id the function `maybe default id' is prominent enough to have its own name, it's `fromMaybe' (exported from Data.Maybe), so unpack = fromMaybe (error "unreachable error")
The second option I like better, for some reason, but it is a bit dangerous, as I have to double check my code to make sure the default value passed to "maybe" cannot possibly be evaluated.
If you have that checked carefully, you could also use unpack = fromJust The difference to fromMaybe yourError is that fromJust produces a generic error message if your check failed, so if there are several 'fromJust's in the code, it doesn't tell you which of your checks failed, while your self- supplied error should be easy to identify. fromJust is a partial function, as such dangerous. Some people say you should *never* use it, but even without going so far, fromJust [and head, tail, ...] should only be used where you are *certain* that you can't get a Nothing. Generally, using it indicates not-so-good design somewhere.
(Alternatively, I could pass in a regular default value, like a blank string, though that is actually more dangerous in my mind because a bad value might be used silently.)
That may be the right thing to do in some circumstances, horribly wrong in others. But when supplying a default value is sensible, you should probably use a fromMaybe or maybe anyway.
Anyway: how do you pros go about handling situations like these?
participants (4)
-
Christopher Howard
-
Daniel Fischer
-
Elvio Toccalino
-
Erik de Castro Lopo