Aleph0
Aleph0

Reputation: 6074

Pattern matching against Just containing a pair

I'm experimenting with Haskell and I'm wondering why I couldn't match against a Just containing a pair. I have little experience with this language and I'm completely lost.

f :: Int -> Maybe (Int, [Int])
f 100 = Nothing
f x = Just (x,[x])

g :: Int -> Maybe Int
g x
 | u==Nothing = Nothing
 | u==(Just (r,s)) = Just r
 where 
  u=f x

So what is wrong with this code. GHC says that r and s are not in scope.

Upvotes: 2

Views: 378

Answers (3)

Zeta
Zeta

Reputation: 105876

If you want to pattern match in a guard, you have to use a pattern guard:

g :: Int -> Maybe Int
g x
  | Just (r,_) <- u = Just r
  | otherwise       = Nothing 
  where 
   u = f x

After all, (==) is a regular function, you need values on both sides to use it. Since r and s aren't known in u == Just (r,s), the compiler gives you your error message.

By the way, taking a Maybe and return Nothing if the value was Nothing or Just (h x) for a function h and Just x is so common, it forms a pattern: fmap. You can write

g :: Int -> Maybe Int
g x = fmap fst (f x)

Upvotes: 7

jeiea
jeiea

Reputation: 2385

Because the guard expression can't do pattern matching.

Guard expression is just like a boolean expression, it can't do binding. It just uses the binding before |, in this case x.

So working solution will be like this.

g :: Int -> Maybe Int
g x = case f x of
  Nothing -> Nothing
  Just (r,_) -> Just r

Upvotes: 6

ymonad
ymonad

Reputation: 12090

You can use case expressions

g :: Int -> Maybe Int
g x =
  case f x of
    Nothing -> Nothing
    Just (r,s) -> Just r

Upvotes: 4

Related Questions