From ebebe006c0e3ff495c30e2bd8a127504c9ed02c4 Mon Sep 17 00:00:00 2001 From: Joel Kaasinen Date: Thu, 10 Mar 2022 08:15:38 +0200 Subject: [PATCH] lecture 2: new section "When to Use Case Expressions" --- part1.html | 2633 +++++++++++++++++++++++++++------------------------- 1 file changed, 1346 insertions(+), 1287 deletions(-) diff --git a/part1.html b/part1.html index ae01747..b51efa9 100644 --- a/part1.html +++ b/part1.html @@ -1504,6 +1504,65 @@ lectureParticipants = [Right 10, Right 13, Left "easter vacation", Rig "statement" Prelude> sentenceType "This is Haskell!" "exclamation" +

2.9.1 When to Use Case Expressions

+

You might be asking, what is the point of having another pattern matching syntax. Well, case expressions have some advantages over equations which we’ll discuss next.

+

Firstly, and perhaps most importantly, case expressions enable us to pattern match against function outputs. We might want to write early morning motivational messages to working (lazy) Haskellers:

+
motivate :: String -> String
+motivate "Monday"    = "Have a nice week at work!"
+motivate "Tuesday"   = "You're one day closer to weekend!"
+motivate "Wednesday" = "3 more day(s) until the weekend!"
+motivate "Thursday"  = "2 more day(s) until the weekend!"
+motivate "Friday"    = "1 more day(s) until the weekend!"
+motivate _           = "Relax! You don't need to work today!"
+

Using a case expression we can run a helper function against the argument and pattern match on the result:

+
motivate :: String -> String
+motivate day = case distanceToSunday day of
+  6 -> "Have a nice week at work!"
+  5 -> "You're one day closer to weekend!"
+  n -> if n > 1
+       then show (n - 1) ++ " more day(s) until the weekend!"
+       else "Relax! You don't need to work today!"
+

By the way, there’s also a third way, guards:

+
motivate :: String -> String
+motivate day
+  | n == 6 = "Have a nice week at work!"
+  | n == 5 = "You're one day closer to weekend!"
+  | n > 1 = show (n - 1) ++ " more day(s) until the weekend!"
+  | otherwise = "Relax! You don't need to work today!"
+  where n = distanceToSunday day - 1
+

We’ll see in a moment how we can define distanceToSunday using equations and case expressions.

+

Secondly, if a helper function needs to be shared among many patterns, then equations don’t work. For example:

+
area :: String -> Double -> Double
+area "square" x = square x
+area "circle" x = pi * square x
+  where square x = x * x
+

This won’t compile because a the where clause only appends to the "circle" case, so the square helper function is not available in the "square" case. On the other hand, we can write

+
area :: String -> Double -> Double
+area shape x = case shape of
+  "square" -> square x
+  "circle" -> pi * square x
+  where square x = x*x
+

Thirdly, case expressions may help to write more concise code in a situation where a (long) function name would have to be repeated multiple times using equations. As we saw above, we might need a function which measures the distance between a given day and Sunday:

+
distanceToSunday :: String -> Int
+distanceToSunday "Monday"    = 6
+distanceToSunday "Tuesday"   = 5
+distanceToSunday "Wednesday" = 4
+distanceToSunday "Thursday"  = 3
+distanceToSunday "Friday"    = 2
+distanceToSunday "Saturday"  = 1
+distanceToSunday "Sunday"    = 0
+

Using a case expression leads into much more concise implementation:

+
distanceToSunday :: String -> Int
+distanceToSunday d = case d of
+  "Monday"    -> 6
+  "Tuesday"   -> 5
+  "Wednesday" -> 4
+  "Thursday"  -> 3
+  "Friday"    -> 2
+  "Saturday"  -> 1
+  "Sunday"    -> 0
+

These three benefits make the case expression a versatile tool in a Haskeller’s toolbox. It’s worth remembering how case works.

+

(Representing weekdays as strings may get the job done, but it’s not the perfect solution. What happens if we apply motivate to "monday" (with all letters in lower case) or "keskiviikko"? In Lecture 5, we will learn a better way to represent things like weekdays.)

2.10 Recap: Pattern Matching

Things you can use as patterns:

3.12.1 Common Errors

-
No instance for (Eq a) arising from a use of ‘==’
+
No instance for (Eq a) arising from a use of ‘==’

You’ve probably tried to use x==Nothing to check if a value is Nothing. Use pattern matching instead. The reason for this error is that values of type Maybe a can’t be compared because Haskell doesn’t know how to compare values of the polymorphic type a. You’ll find more about this in the next lecture. Use pattern matching instead of == for now.

4 Lecture 4: Real Classy