-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathW5.hs
305 lines (253 loc) · 9.62 KB
/
W5.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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
module W5 where
import System.Random
import Data.List
-- Week 5:
-- - using typeclasses
-- - implementing typeclasses
-- - forcing/laziness
--
-- Useful type classes to know:
-- - Eq
-- - Ord
-- - Show
-- - Num
-- - Functor
------------------------------------------------------------------------------
-- Ex 1: hey, did you know you can implement your own operators in
-- Haskell? Implement the operator %$ that combines two strings like
-- this:
--
-- "aa" %$ "foo" ==> "aafooaa"
--
-- and the operator *! that takes a value and a number and produces a
-- list that repeats the value that many times:
--
-- 3 *! True ==> [True,True,True]
(%$) :: String -> String -> String
x %$ y = undefined
(*!) :: Int -> a -> [a]
n *! val = undefined
------------------------------------------------------------------------------
-- Ex 2: implement the function allEqual which returns True if all
-- values in the list are equal.
--
-- Examples:
--
-- allEqual [] ==> True
-- allEqual [1,2,3] ==> False
-- allEqual [1,1,1] ==> True
--
-- PS. check out the error message you get with your implementation if
-- you remove the Eq a => constraint from the type!
allEqual :: Eq a => [a] -> Bool
allEqual xs = undefined
------------------------------------------------------------------------------
-- Ex 3: implement the function secondSmallest that returns the second
-- smallest value in the list, or Nothing if there is no such value.
--
-- NB! If the smallest value of the list occurs multiple times, it is
-- also the second smallest. See third example.
--
-- Examples:
--
-- secondSmallest [1.0] ==> Nothing
-- secondSmallest [1,2] ==> Just 2
-- secondSmallest [1,1,2] ==> Just 1
-- secondSmallest [5,3,7,2,3,1] ==> Just 2
secondSmallest :: Ord a => [a] -> Maybe a
secondSmallest xs = undefined
------------------------------------------------------------------------------
-- Ex 4: Implement the function incrementKey, that takes a list of
-- (key,value) pairs, and adds 1 to all the values that have the given key.
--
-- You'll need to add a _class constraint_ to the type of incrementKey
-- to make the function work!
--
-- The function needs to be generic and handle all compatible types,
-- see the examples.
--
-- Examples:
-- incrementKey True [(True,1),(False,3),(True,4)] ==> [(True,2),(False,3),(True,5)]
-- incrementKey 'a' [('a',3.4)] ==> [('a',4.4)]
incrementKey :: k -> [(k,v)] -> [(k,v)]
incrementKey = undefined
------------------------------------------------------------------------------
-- Ex 5: compute the average of a list of values of the Fractional
-- class.
--
-- There is no need to handle the empty list case.
--
-- Hint! since Fractional is a subclass of Num, you have all
-- arithmetic operations available
--
-- Hint! you can use the function fromIntegral to convert the list
-- length to a Fractional
average :: Fractional a => [a] -> a
average xs = undefined
------------------------------------------------------------------------------
-- Ex 6: define an Eq instance for the type Foo below.
--
-- (Do not use `deriving Eq`.)
data Foo = Bar | Quux | Xyzzy
deriving Show
instance Eq Foo where
(==) = error "implement me"
------------------------------------------------------------------------------
-- Ex 7: implement an Ord instance for Foo so that Quux < Bar < Xyzzy
instance Ord Foo where
compare = error "implement me?"
(<=) = error "and me?"
min = error "and me?"
max = error "and me?"
------------------------------------------------------------------------------
-- Ex 8: here is a type for a 3d vector. Implement an Eq instance for it.
data Vector = Vector Integer Integer Integer
deriving Show
instance Eq Vector where
(==) = error "implement me"
------------------------------------------------------------------------------
-- Ex 9: implementa Num instance for Vector such that all the
-- arithmetic operations work componentwise.
--
-- You should probably check the docs for which methods Num has!
--
-- Examples:
--
-- Vector 1 2 3 + Vector 0 1 1 ==> Vector 1 3 4
-- Vector 1 2 3 * Vector 0 1 2 ==> Vector 0 2 6
-- abs (Vector (-1) 2 (-3)) ==> Vector 1 2 3
-- signum (Vector (-1) 2 (-3)) ==> Vector (-1) 1 (-1)
instance Num Vector where
------------------------------------------------------------------------------
-- Ex 10: compute how many times each value in the list occurs. Return
-- the frequencies as a list of (frequency,value) pairs.
--
-- Hint! feel free to use functions from Data.List
--
-- Example:
-- freqs [False,False,False,True]
-- ==> [(3,False),(1,True)]
freqs :: (Eq a, Ord a) => [a] -> [(Int,a)]
freqs xs = undefined
------------------------------------------------------------------------------
-- Ex 11: implement an Eq instance for the following binary tree type
data ITree = ILeaf | INode Int ITree ITree
deriving Show
instance Eq ITree where
(==) = error "implement me"
------------------------------------------------------------------------------
-- Ex 12: here is a list type parameterized over the type it contains.
-- Implement an instance "Eq a => Eq (List a)" that compares elements
-- of the lists.
data List a = Empty | LNode a (List a)
deriving Show
instance Eq a => Eq (List a) where
(==) = error "implement me"
------------------------------------------------------------------------------
-- Ex 13: Implement the function incrementAll that takes a functor
-- value containing numbers and increments each number inside by one.
--
-- Examples:
-- incrementAll [1,2,3] ==> [2,3,4]
-- incrementAll (Just 3.0) ==> Just 4.0
incrementAll :: (Functor f, Num n) => f n -> f n
incrementAll x = undefined
------------------------------------------------------------------------------
-- Ex 14: below you'll find a type Result that works a bit like Maybe,
-- but there are two different types of "Nothings": one with and one
-- without an error description.
--
-- Implement the instance Functor Result
data Result a = MkResult a | NoResult | Failure String
deriving (Show,Eq)
instance Functor Result where
fmap f result = error "implement me"
------------------------------------------------------------------------------
-- Ex 15: Implement the instance Functor List (for the datatype List
-- from ex 12)
instance Functor List where
------------------------------------------------------------------------------
-- Ex 16: Fun a is a type that wraps a function Int -> a. Implement a
-- Functor instance for it.
--
-- Figuring out what the Functor instance should do is most of the
-- puzzle.
data Fun a = Fun (Int -> a)
runFun :: Fun a -> Int -> a
runFun (Fun f) x = f x
instance Functor Fun where
------------------------------------------------------------------------------
-- Ex 17: Define the operator ||| that works like ||, but forces its
-- _right_ argument instead of the left one.
--
-- Examples:
-- False ||| False ==> False
-- True ||| False ==> True
-- undefined ||| True ==> True
-- False ||| undefined ==> an error!
--
-- NB! Do not use any library functions in your definition. Just
-- pattern matching.
(|||) :: Bool -> Bool -> Bool
x ||| y = undefined
------------------------------------------------------------------------------
-- Ex 18: Define the function boolLength, that returns the length of a
-- list of booleans and forces all of the elements
--
-- Examples:
-- boolLength [False,True,False] ==> 3
-- boolLength [False,undefined] ==> an error!
-- Huom! length [False,undefined] ==> 2
boolLength :: [Bool] -> Int
boolLength xs = undefined
------------------------------------------------------------------------------
-- Ex 19: this and the next exercise serve as an introduction for the
-- next week.
--
-- The module System.Random has the typeclass RandomGen that
-- represents a random generator. The class Random is for values that
-- can be randomly generated by RandomGen.
--
-- The relevant function in System.Random is
-- random :: (Random a, RandomGen g) => g -> (a, g)
-- that takes a random generator and returns a random value, and the
-- new state of the generator (remember purity!)
--
-- Implement the function threeRandom that generates three random
-- values. You don't need to return the final state of the random
-- generator (as you can see from the return type).
--
-- NB! if you use the same generator multiple times, you get the same
-- output. Remember to use the new generator returned by random.
--
-- NB! the easiest way to get a RandomGen value is the function
-- mkStdGen that takes a seed and returns a random generator.
--
-- Examples:
-- *W5> threeRandom (mkStdGen 1) :: (Int,Int,Int)
-- (7917908265643496962,-1017158127812413512,-1196564839808993555)
-- *W5> threeRandom (mkStdGen 2) :: (Bool,Bool,Bool)
-- (True,True,False)
threeRandom :: (Random a, RandomGen g) => g -> (a,a,a)
threeRandom g = undefined
------------------------------------------------------------------------------
-- Ex 20: given a Tree (same type as on Week 3), randomize the
-- contents of the tree.
--
-- That is, you get a RandomGen and a Tree, and you should return a
-- Tree with the same shape, but random values in the Nodes.
--
-- This time you should also return the final state of the RandomGen
--
-- Hint! the recursive solution is straightforward, but requires
-- careful threading of the RandomGen versions.
--
-- Examples:
-- *W5> randomizeTree (Node 0 (Node 0 Leaf Leaf) Leaf) (mkStdGen 1) :: (Tree Char, StdGen)
-- (Node '\603808' (Node '\629073' Leaf Leaf) Leaf,1054756829 1655838864)
-- *W5> randomizeTree (Node True Leaf Leaf) (mkStdGen 2) :: (Tree Int, StdGen)
-- (Node (-2493721835987381530) Leaf Leaf,1891679732 2103410263)
data Tree a = Leaf | Node a (Tree a) (Tree a)
deriving Show
randomizeTree :: (Random a, RandomGen g) => Tree b -> g -> (Tree a,g)
randomizeTree t g = undefined