PDA

View Full Version : Another Haskell Question


Baalthazaq
08-16-2004, 11:17 AM
Just wondering if there is an easy way of doing this in Haskell. Just fewer lines:

I have two data types, and some other functions which are immaterial to the actual question.

The following are all the parts that work:

> data Day = Sunday | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday deriving (Show, Eq)

> data Weather = Overcast | Wind | Rain | Snow | Sun | Cold deriving (Show, Eq)

> typical :: Day -> Weather -> Bool
> typical _ Cold = True
> typical a Snow = is_weekend a
> typical a Sun = is_weekend a
> typical _ _ = False

Now, above the >typical _ _ = False line there is a line I've missed.

What I WANT to write is something along the lines of:

>typical (Sunday | Monday | Tuesday) (Overcast | Wind) = True

Instead I've opted for writing each case out independantly because I couldn't get Haskell to compile either this, or any of the other variants of this line.

I'm sure (just because it's haskell, and it's lovely like that most of the time), that I'm just doing something minorly wrong.

slidewinder
08-29-2004, 03:31 PM
No, you can't use an "or" in a pattern match, AFAIK, though it might be nice if you could. In this case, because your ranges cover successive elements of your data types, you could derive Ord, and then add a check inside a guard like:


> data Day = Sunday | Monday | Tuesday | Wednesday | Thursday | Friday |
> Saturday deriving (Show, Eq, Ord)

> data Weather = Overcast | Wind | Rain | Snow | Sun | Cold
> deriving (Show, Eq, Ord)

> typical :: Day -> Weather -> Bool
> typical _ Cold = True
> typical a Snow = is_weekend a
> typical a Sun = is_weekend a
> typical d w | (d < Wednesday) && (w < Rain) = True
> | otherwise = False

> is_weekend Saturday = True
> is_weekend Sunday = True


You could get the same effect by deriving Enum instead, and then using "fromEnum day" and comparing it to a number, but I think the Ord way is nicer here. That's not a general answer to your problem, though, because there are presumably going to be times when you want to check for possibilities that aren't consecutive within your data type.

In that case, you could again use guards, and have guard conditions like


> typical' d w | (d == Sunday || d == Wednesday) && (w == Wind || w == Sun) = True


which might be a little better than writing out individual pattern matches in that the rhs isn't repeated so much, but will get ugly pretty fast if your tests get complicated. If that happens, you can "refactor" your checks by creating functions like, say, "wintery" that return true for Snow or Cold, and then using those functions inside the guard of "typical".