-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwhere.hs
74 lines (58 loc) · 2.76 KB
/
where.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
-- # http://learnyouahaskell.com/syntax-in-functions#where
-- LOAD THIS FILE WITH ":l where" within repl (ghci)
-- and reload with ":r"
-- Where
-- Above (in guards.hs) we repeated ourselves three times when calculating BMI.
-- It would be ideal if we could calculate it once,
-- bind it to a name and then use that name instead of the expression.
calcBmiTell' :: (RealFloat a) => a -> a -> String
calcBmiTell' weight height
| bmi <= 18.5 = "You're underweight, you emo, you!"
| bmi <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!"
| bmi <= 30.0 = "You're fat! Lose some weight, fatty!"
| otherwise = "You're a whale, congratulations!"
where bmi = weight / height ^ 2
-- Lets go further!
betterBmiTell :: (RealFloat a) => a -> a -> String
betterBmiTell weight height
| bmi <= skinny = "You're underweight, you emo, you!"
| bmi <= normal = "You're supposedly normal. Pffft, I bet you're ugly!"
| bmi <= fat = "You're fat! Lose some weight, fatty!"
| otherwise = "You're a whale, congratulations!"
where bmi = weight / height ^ 2
skinny = 18.5
normal = 25.0
fat = 30.0
-- The names we define in the where section of a function are only visible to that function.
-- where bindings aren't shared across function bodies of different patterns.
-- Notice that all the names are aligned at a single column.
-- If we don't align them nice and proper, Haskell gets confused because
-- then it doesn't know they're all part of the same block.
-- You can also use where bindings to pattern match.
-- Get a first and a last name and give someone back their initials.
initials :: String -> String -> String
initials firstname lastname = [f] ++ ". " ++ [l] ++ "."
where (f:_) = firstname
(l:_) = lastname
-- We could have done this pattern matching directly in the function's parameters
-- (it would have been shorter and clearer actually) but this just goes to show
-- that it's possible to do it in where bindings as well.
-- You can also define functions.
-- Lets take a list of weight-height pairs and return a list of BMIs.
calcBmis :: (RealFloat a) => [(a, a)] -> [a]
calcBmis xs = [bmi w h | (w, h) <- xs]
where bmi weight height = weight / height ^ 2
-- where bindings can also be nested.
-- It's a common idiom to make a function
-- and define some helper function in its where clause
-- and then to give those functions helper functions as well,
-- each with its own where clause.
doublePlusOne x = plusOne x
where plusOne x = double x + 1
where double x = x * 2
-- You can use pattern matching in where;
describeList' :: [a] -> String
describeList' xs = "The list is " ++ what xs
where what [] = "empty."
what [x] = "a singleton list."
what xs = "a longer list."