question about pattern guards

Hi, I have a question related to pattern guards in the syntax of Haskell 2010. Why is it not possible to combine them with a logical OR, instead of the comma that stands for a logical AND? http://www.haskell.org/ghc/docs/latest/html/users_guide/syntax-extns.html#pa... Thanks, TP

Daniel Trstenjak wrote:
Why is it not possible to combine them with a logical OR, instead of the comma that stands for a logical AND?
The '|' already acts as the "OR", why should you need another one?
Thanks for your answer. Consider the following example: ------------------ type Foo = Maybe Int f :: Foo -> Foo -> Int f x y | Just n <- x = 1 | Just n <- y = 1 | otherwise = 2 main = do print $ f (Just 3) Nothing print $ f Nothing (Just 3) print $ f (Just 3) (Just 3) print $ f Nothing Nothing ------------------ It works correctly, but I am compelled to duplicate `1` even if I know that the result of `f x y` will be `1` if either `x` or `y` is `Just n`. Here the duplication is limited in terms of number of characters, but this may not always be so. So I would like to do: ------------------ type Foo = Maybe Int f :: Foo -> Foo -> Int f x y | (Just n <- x) || (Just n <- y) = 1 | otherwise = 2 main = do print $ f (Just 3) Nothing print $ f Nothing (Just 3) print $ f (Just 3) (Just 3) print $ f Nothing Nothing ------------------ But the `||` yields a parse error, `||` is not supported in pattern guards. Whereas it is supported in classical guards: ------------------ f :: Int -> Int f n | n == 1 = 1 | n < 1 || n > 4 = 2 | otherwise = 3 main = do print $ f 1 print $ f 5 print $ f (-1) print $ f 2 ------------------ What am I missing? Thanks in advance, TP

I believe the structure you are looking for is called an "Or Pattern", which isn't available in Haskell. Or Patterns are available in other FP languages.
One way you could reduce the duplication from the right hand side, for more complicated examples, would be to create a separate function and call it instead.
Cheers,
Stuart
On 21 Sep 2013, at 12:08, TP
Daniel Trstenjak wrote:
Why is it not possible to combine them with a logical OR, instead of the comma that stands for a logical AND?
The '|' already acts as the "OR", why should you need another one?
Thanks for your answer. Consider the following example:
------------------ type Foo = Maybe Int
f :: Foo -> Foo -> Int f x y | Just n <- x = 1 | Just n <- y = 1 | otherwise = 2
main = do
print $ f (Just 3) Nothing print $ f Nothing (Just 3) print $ f (Just 3) (Just 3) print $ f Nothing Nothing ------------------
It works correctly, but I am compelled to duplicate `1` even if I know that the result of `f x y` will be `1` if either `x` or `y` is `Just n`. Here the duplication is limited in terms of number of characters, but this may not always be so. So I would like to do:
------------------ type Foo = Maybe Int
f :: Foo -> Foo -> Int f x y | (Just n <- x) || (Just n <- y) = 1 | otherwise = 2
main = do
print $ f (Just 3) Nothing print $ f Nothing (Just 3) print $ f (Just 3) (Just 3) print $ f Nothing Nothing ------------------
But the `||` yields a parse error, `||` is not supported in pattern guards. Whereas it is supported in classical guards:
------------------ f :: Int -> Int f n | n == 1 = 1 | n < 1 || n > 4 = 2 | otherwise = 3
main = do
print $ f 1 print $ f 5 print $ f (-1) print $ f 2 ------------------
What am I missing?
Thanks in advance,
TP
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

That works with Maybe, but not with lists. If I want at least one of xs or ys to match a two element list then f xs ys | [_,_] <- xs <|> ys = ... won't behave as expected, since <|> is ++ for lists, so f [1] [2] will match the pattern. Undoubtedly there are other type- and example-specific ways to encode the alternative for lists and other examples. I think what the OP is asking though, is why pattern alternatives aren't allowed in pattern guards (or in patterns in function definitions, or in case statements). I'm guessing that the major problem is binding? Suppose the token "or" introduces pattern alternatives: g xs ys | (_:_:xrest) <- xs) or ([y1] <- ys) = ... The pattern matches if xs has at least two elements or if ys is a one element list. But after the match you don't know which names have been bound. I guess there are ways to deal with that problem, like requiring every pattern alternative to bind exactly the same set of names and types, but sounds like that would get pretty hairy. How do other languages that allow "or patterns" handle binding? Graham On 21/09/2013 9:34 AM, Daniel Trstenjak wrote:
What am I missing?
You can combine booleans by '||', but 'Just n <- x' doesn't result to a boolean.
You can use '<|>' from 'Control.Applicative' to get the desired behavoir.
f x y | Just _ <- x <|> y = 1 | otherwise = 2
Greetings, Daniel
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (4)
-
Daniel Trstenjak
-
Graham Gill
-
Stuart Gale
-
TP