[Haskell-cafe] Disjunctive patterns

Øystein Kolsrud kolsrud at gmail.com
Thu Dec 8 13:48:01 CET 2011


Or perhaps this?

data T = Foo Int | Bar Int | Baz

fooBar (Foo a) = Just a
fooBar (Bar a) = Just a
fooBar _       = Nothing

foo :: T -> T -> Int
foo x y = sum $ catMaybes $ map fooBar [x,y]

/Øystein

On Thu, Dec 8, 2011 at 1:15 PM, Emil Axelsson <emax at chalmers.se> wrote:

> Instead of pattern guards you can use ViewPatterns:
>
>  http://hackage.haskell.org/**trac/ghc/wiki/ViewPatterns<http://hackage.haskell.org/trac/ghc/wiki/ViewPatterns>
>
> This reduces some of the noise.
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**~~
> {-# LANGUAGE ViewPatterns #-}
>
>
> data T = Foo Int | Bar Int | Baz
>
> fooBar (Foo a) = Just a
> fooBar (Bar a) = Just a
> fooBar _       = Nothing
>
>
> foo :: T -> T -> Int
> foo x y = case (x,y) of
>  (fooBar -> Just a, fooBar -> Just b) -> a + b
>  (Bar a, Baz) -> -a
>
>  (Foo a, Baz) -> a
>  _ -> 0
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**~~
>
> / Emil
>
>
> 2011-12-08 11:13, Asger Feldthaus skrev:
>
>> Haskell doesn't seem to support disjunctive patterns, and I'm having a
>> difficult time writing good Haskell code in situations that would
>> otherwise call for that type of pattern.
>>
>> Suppose for an example I have this data type:
>>
>> data T = Foo Int | Bar Int | Baz
>>
>> In OCaml I can write something like:
>>
>> (* foo : T -> T -> int *)
>> fun foo x y = match (x,y) with
>>   | (Foo a | Bar a, Foo b | Bar b) -> a + b
>>   | (Baz, Foo a)
>>   | (Bar a, Baz) -> -a
>>   | (Baz, Bar a)
>>   | (Foo a, Baz) -> a
>>   | _ -> 0
>>
>> In Haskell I can't find any equivalent to the disjunctive pattern. If
>> expanded naively, my Haskell version would look like this:
>>
>> foo :: T -> T -> Int
>> foo x y = case (x,y) of
>>   (Foo a, Foo b) -> a + b
>>   (Foo a, Bar b) -> a + b
>>   (Bar a, Foo b) -> a + b
>>   (Bar a, Bar b) -> a + b
>>   (Baz, Foo a) -> -a
>>   (Bar a, Baz) -> -a
>>   (Baz, Bar a) -> a
>>   (Foo a, Baz) -> a
>>   _ -> 0
>>
>> While my example is still managable in size, this quickly goes out of
>> hand in practice. I've tried using pattern guards but with limited
>> success. For example:
>>
>> foo2 :: T -> T -> Int
>> foo2 x y = case (x,y) of
>>   (x,y) | Just a <- open x,
>>           Just b <- open y ->
>>             a+b
>>   (Baz, Foo a) -> -a
>>   (Bar a, Baz) -> -a
>>   (Baz, Bar a) -> a
>>   (Foo a, Baz) -> a
>>   _ -> 0
>>   where
>>     open (Foo x) = Just x
>>     open (Bar x) = Just x
>>     open Baz = Nothing
>>
>> I admit it doesn't look that bad in my crafted example, but this
>> approach doesn't seem to well work for me in practice. In any case, it's
>> still far more verbose than the disjunctive pattern version.
>>
>> Nesting the case expressions instead of tuple-matching can reduce some
>> code duplication, but in general it becomes really verbose, and it is
>> easy to make mistakes when you have partially overlapped patterns in the
>> disjunctive-pattern version. Here's the example with nested cases:
>>
>> foo3 :: T -> T -> Int
>> foo3 x y = case x of
>>   Foo a -> case y of
>>     Foo b -> a+b
>>     Bar b -> a+b
>>     Baz -> a
>>   Bar a -> case y of
>>     Foo b -> a+b
>>     Bar b -> a+b
>>     Baz -> -a
>>   Baz -> case y of
>>     Foo b -> -b
>>     Bar b -> b
>>     Baz -> 0
>>
>> What do people do in this situation - is there a good trick I've
>> overlooked? And is there some reason why Haskell does not support
>> disjunctive patterns?
>>
>> Thanks,
>> Asger
>>
>>
>> ______________________________**_________________
>> Haskell-Cafe mailing list
>> Haskell-Cafe at haskell.org
>> http://www.haskell.org/**mailman/listinfo/haskell-cafe<http://www.haskell.org/mailman/listinfo/haskell-cafe>
>>
>
> ______________________________**_________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/**mailman/listinfo/haskell-cafe<http://www.haskell.org/mailman/listinfo/haskell-cafe>
>



-- 
Mvh Øystein Kolsrud
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20111208/2b322b37/attachment.htm>


More information about the Haskell-Cafe mailing list