-
Notifications
You must be signed in to change notification settings - Fork 0
/
Lesson3TuplesRecursion.hs
152 lines (117 loc) · 3.02 KB
/
Lesson3TuplesRecursion.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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
module Lesson3TuplesRecursion where
import Data.List
-- * Tuples: unlike lists, we know that these data exist
caII_854 :: (String, Float)
caII_854 = ("Calcium II 8542", 8542)
heI :: (String, Float)
heI = ("Helium I", 10830)
hello :: (String, String)
hello = ("Fake", "news")
feI :: (String, Float)
feI = ("Iron I", 6302)
ha :: (String, Float)
ha = ("Hydrogen Alpha", 6562)
spectralLines :: [(String, Float)]
spectralLines =
[caII_854, heI, feI, ha]
-- * Destructuring = Pattern Matching
name :: (String, Float) -> String
name (n, _) = n
wavelength :: (String, Float) -> Float
wavelength (_, wl) = wl
-- TODO: find the wavelength of the last spectral line in the list
-- return 0 if empty
-- hint: drop, length, where
lastWavelength :: [(String, Float)] -> Float
lastWavelength sls = error "TODO"
-- * type aliases!
type Wavelength = Float
type LineName = String
type SpectralLine = (LineName, Wavelength)
-- * Simple Recursion!
wavelengths :: [SpectralLine] -> [Wavelength]
wavelengths [] = []
wavelengths (a : as) = wavelength a : wavelengths as
lineNames :: [SpectralLine] -> [LineName]
lineNames [] = []
lineNames (sl : sls) = name sl : lineNames sls
-- what's different between the two?
-- just 'wavelength x'
-- Higher Order Functions
props :: (a -> b) -> [a] -> [b]
props _ [] = []
props f (a : as) = f a : props f as
-- `prop` is the same as `map`
-- :type map
wavelengths2 as = map wavelength as
lineNames2 as = map name as
-- `filter` items from a list
-- lambda functions
linesBelow :: Wavelength -> [SpectralLine] -> [SpectralLine]
linesBelow wl lines =
filter (\sl -> wavelength sl < wl) lines
where
isBelow sl = wavelength sl < wl
-- Maybe (Optional) is like list with 0 or 1 items, or a nullable value
message :: Maybe String
-- message = Nothing
message = Just "hello"
-- We can make a version of headSafe (Lesson 2) that makes the caller handle missing values
headSafe :: [a] -> Maybe a
headSafe [] = Nothing
headSafe (a : _) = Just a
-- TODO: identify the spectral line, matches if within 10 angstroms
-- hint: Data.List module?
-- hint: headSafe?
identifyLine :: Wavelength -> [SpectralLine] -> Maybe SpectralLine
identifyLine wl lines = error "TODO"
-- Alternatively, use custom if/else logic with guards
identifyLine' :: Wavelength -> Maybe SpectralLine
identifyLine' wl
| 8535 <= wl && wl <= 8550 = Just caII_854
| 6297 <= wl && wl <= 6305 = Just feI
| distance wl heI <= 10 = Just heI
| distance wl ha <= 10 = Just ha
| otherwise = Nothing
where
distance wl line = abs $ wavelength line - wl
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-- DONE: solutions
lastWavelength2 :: [(String, Float)] -> Float
lastWavelength2 sls =
getWavelength $ drop (length sls - 1) sls
where
getWavelength [p] = wavelength p
getWavelength _ = 0
identifyLine2 :: Wavelength -> [SpectralLine] -> Maybe SpectralLine
identifyLine2 wl lines =
find (within10Angstroms wl) lines
where
distance wl line = abs $ wavelength line - wl
within10Angstroms wl line = distance wl line <= 10