This repository has been archived by the owner on Apr 9, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathLec06Live.hs
216 lines (146 loc) · 3.92 KB
/
Lec06Live.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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
module Lec06Live where
import Data.Char
import Prelude hiding (Maybe (..), String, Monoid (..))
{- LECTURE 06 : DECLARING TYPES AND CLASSES -}
{- PART I : TYPE SYNONYMS -}
-- Useful for documentation
-- Useful to prevent repeating yourself
-- 1. String
-- typedef int my_int;
type Metres = Int
type DB = [(String,Int,Double)]
type String = [Char]
add :: Metres -> Metres -> Metres
add x y = x + y
-- 2. Positions
type Position = (Int,Int)
origin :: Position
origin = (0,0)
-- 3. Transformations
type Transformation = Position -> Position
goNorth :: Transformation
goNorth (x,y) = (x,y+1)
-- 4. Parameterised abbreviations
type Pair a = (a,a)
type Position' = Pair Int
-- type List a = Maybe (a, List a)
{- PART II : DATA TYPES -}
-- 1. Enumerations
data Direction
= North
| South
| East
| West
deriving Show
-- 2. Maybe (replacement for 'null')
-- https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare
data Maybe a
= Nothing
| Just a
deriving Show
hd :: [a] -> Maybe a
hd [] = Nothing
hd (x:xs) = Just x
-- 3. "Make Illegal States Unrepresentable"
{-
public class Student {
// never null!
@Nonnull
private Optional<String> name;
// at least one of these is non-null
private String registrationNumber;
private String dsUsername;
// ...
}
(Optional)
-}
data Student =
MkStudent { studentName :: String
, details :: StudentDetails
}
deriving Show
data StudentDetails
= OnlyRegNumber String
| OnlyUsername String
| BothRegAndUsername String String
deriving Show
-- 4. Trees
data List a
= Nil
| Cons a (List a)
deriving Show
data Tree a
= Leaf
| Node (Tree a) a (Tree a)
deriving Show
exampleTree :: Tree Int
exampleTree = Node (Node Leaf 1 Leaf) 2 (Node Leaf 3 Leaf)
-- 5. XML / JSON
data XML
= Elem { tagName :: String, attributes :: [(String,String)], children :: [XML] }
| Text String
data JSON
= Null
| Boolean Bool
| String String
| Number Double
| Object [(String,JSON)]
| Array [JSON]
deriving (Show)
insert :: (a -> a -> Ordering) -> a -> [a] -> [a]
insert cmp x [] = [x]
insert cmp x (y:ys) = case cmp x y of
EQ -> x : y : ys
LT -> x : y : ys
GT -> y : insert cmp x ys
sort :: (a -> a -> Ordering) -> [a] -> [a]
sort cmp [] = []
sort cmp (x:xs) = insert cmp x (sort cmp xs)
instance Eq JSON where
Null == Null = True
--(==) Null Null = True
Boolean b1 == Boolean b2 = b1 == b2
String s1 == String s2 = s1 == s2
Number d1 == Number d2 = d1 == d2
Object fields1 == Object fields2 =
sort (\(nm1,_) (nm2,_) -> compare nm1 nm2) fields1
== sort (\(nm1,_) (nm2,_) -> compare nm1 nm2) fields2
Array jsons1 == Array jsons2 = jsons1 == jsons2
_ == _ = False
upperCase :: JSON -> JSON
upperCase Null = Null
upperCase (Boolean b) = Boolean b
upperCase (String s) = String (map toUpper s)
upperCase (Number d) = Number d
upperCase (Object fields) = Object (map (\(nm,j) -> (nm, upperCase j)) fields)
upperCase (Array jsons) = Array (map upperCase jsons)
testJSON :: JSON
testJSON = Object [ ("field1", Number 2.0)
, ("field2", String "two point oh")
]
testJSON' :: JSON
testJSON' = Object [ ("field2", String "two point oh")
, ("field1", Number 2.0)
]
-- { 'field1': 2.0, 'field2': "TWO POINT OH" }
{- PART III : TYPE CLASSES -}
-- 1. Show
-- 2. Eq
-- 3. Monoid
class Monoid a where
mempty :: a
mappend :: a -> a -> a
instance Monoid Int where
mempty = 0
mappend = (+)
instance Monoid [a] where
mempty = []
mappend = (++)
instance Monoid Bool where
mempty = True
mappend = (&&)
(<>) :: Monoid a => a -> a -> a
(<>) = mappend
crush :: Monoid a => [a] -> a
crush [] = mempty
crush (x:xs) = x <> crush xs