The Occasional Occurence
Evolution of a Haskell Function
March 11, 2010 at 01:23 PM | categories: Python, Software, computing, GeneralI'm going through Real World Haskell trying to get a handle on the Haskell programming language. Python is my current language of choice, but I like to learn new programming languages too.
So last night I was going over the chapter that introduces 'let', 'where', 'case' and guards and I wanted to try them out. I contrived a simple situation where I thought I could use them.
I made some Contestants and wanted to see if they were "valid" for some definition of the word. I chose that they had to have a real value for age (not Missing) and be 30 years old or older (I'm pretty sure the game is called "Who Wants to Be a 30-year-old Computer Nerd?").
Here is my implementation.
-- my parameterized type data Perhaps a = Is a | Missing deriving (Show) -- definition of a Contestant data Contestant = Contestant { name :: String, age :: Perhaps Int } deriving (Show) -- some contestants contestant1 = Contestant "Christian" (Is 31) contestant2 = Contestant "Sarah" Missing contestant3 = Contestant "Curtis" (Is 6) -- the validation logic contestantValid :: Contestant -> Bool contestantValid c = case age c of Missing -> False Is true_age -> oldenough true_age where oldenough a | a >= 30 = True | a < 30 = False -- some code to print the results of running the validation against contestants main = do print $ (contestant1, contestantValid contestant1) print $ (contestant2, contestantValid contestant2) print $ (contestant3, contestantValid contestant3)
I was pretty proud of myself. I used 'case', 'where' and guards (not to mention parameterized types - I reimplemented Maybe/Just/Nothing as Perhaps/Is/Missing).
But man, it seemed like a lot of code to do something simple.
As I was falling asleep I realized how I could simplify it. I could use pattern matching to easily handle the Missing case. It would also let me pull the age out of a Contestant with ease too.
Here is the contestantValid function updated to reflect that.
contestantValid :: Contestant -> Bool contestantValid (Contestant _ Missing) = False contestantValid (Contestant _ (Is age)) | age >= 30 = True | age < 30 = False
Quite a bit simpler. I patted myself on the back. It was less fancy than the first version, but at least I had some guards in there.
Then it hit me. I didn't need the guards.
contestantValid :: Contestant -> Bool contestantValid (Contestant _ Missing) = False contestantValid (Contestant _ (Is age)) = age >= 30
Well, so much for 'where', 'case' and guards. It sure is a boring function now, but I think the process of how I got there is interesting.
cw