using the joker "_" on a constructor

Hi, I have a question about pattern matching. Consider the following code: ------------------ data Foo = Bar Int | Foo Int f :: Foo -> Bool f (Foo n) | even n = True | odd n = False f (Bar n) | even n = True | odd n = False main = do print $ f $ Bar 1 print $ f $ Bar 2 print $ f $ Foo 1 print $ f $ Foo 2 ------------------ Why is it not possible to simply write for f: f v = case v of _ n | even n -> True _ n | odd n -> False or f (_ n) | even n = True | odd n = False (in both cases we get a parse error)? Thanks, TP

On Wed, Sep 18, 2013 at 9:08 PM, TP
f :: Foo -> Bool f (Foo n) | even n = True | odd n = False f (Bar n) | even n = True | odd n = False
(1) Since even is monomorphized to Int -> Bool, you can just write f (Foo n) = even n f (Bar n) = even n (2) Since the sum subtypes are the same, you can write data Foo = Foo {myN :: Int} | Bar {myN :: Int} f :: Foo -> Bool f x = even $ myN x (3) As to your original question why the underscore _ can't be overloaded for this, I dunno. It /may/ be possible. Seems rare in practice. You could always apply the type isomorphism to get data FooT = Foo | Bar data Foo = Foo Int FooT f (Foo n _) = even n -- Kim-Ee

It has to know the constructor in order to know the type of n. In your
case they are both int, but in the general case they could be completely
different types and therefore you could not just use the constructors
interchangeably.
If you want to write this I would go:
data Foo = Bar Int | Foo Int
def unFoo (Bar n) = n
def unFoo (Foo n) = n
f v = if even (unFoo n) then True else False
You could also define the data type as
data Foo = Bar { unFoo :: Int } | Foo { unFoo :: Int }
As long as you make sure unFoo works for every possibility (otherwise it
would be a partial function that could throw an exception).
On Wed, Sep 18, 2013 at 10:08 AM, TP
Hi,
I have a question about pattern matching. Consider the following code:
------------------ data Foo = Bar Int | Foo Int
f :: Foo -> Bool f (Foo n) | even n = True | odd n = False f (Bar n) | even n = True | odd n = False
main = do
print $ f $ Bar 1 print $ f $ Bar 2 print $ f $ Foo 1 print $ f $ Foo 2 ------------------
Why is it not possible to simply write for f:
f v = case v of _ n | even n -> True _ n | odd n -> False
or
f (_ n) | even n = True | odd n = False
(in both cases we get a parse error)?
Thanks,
TP
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

In order to avoid your duplicate code consider to define "Foo" as follows: data Foo = F FB Int data FB = Foo | Bar f (F _ n) = even n and insert the constructor "F" after the final "$" in:
print $ f $ Bar 1 print $ f $ Bar 2 print $ f $ Foo 1 print $ f $ Foo 2
HTH Christian Am 18.09.2013 16:08, schrieb TP:
Hi,
I have a question about pattern matching. Consider the following code:
------------------ data Foo = Bar Int | Foo Int
f :: Foo -> Bool f (Foo n) | even n = True | odd n = False f (Bar n) | even n = True | odd n = False
main = do
print $ f $ Bar 1 print $ f $ Bar 2 print $ f $ Foo 1 print $ f $ Foo 2 ------------------
Why is it not possible to simply write for f:
f v = case v of _ n | even n -> True _ n | odd n -> False
or
f (_ n) | even n = True | odd n = False
(in both cases we get a parse error)?
Thanks,
TP
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Christian Maeder wrote:
In order to avoid your duplicate code consider to define "Foo" as follows:
data Foo = F FB Int data FB = Foo | Bar
f (F _ n) = even n
Thanks a lot. Your solution, also given by Kim-Ee Yeoh, is the one I prefer: • the common features are factorized in the type; • the values are deconstructed by pattern matching maybe in a clearer way; • `_` is explicitly used, making clear in a blink of an eye that we have some common behavior over several types. TP
participants (4)
-
Christian Maeder
-
David McBride
-
Kim-Ee Yeoh
-
TP