@@ -145,8 +145,75 @@ object GettingStartedWithFPSection extends FlatSpec with Matchers with org.scala
145
145
}
146
146
147
147
isSorted(Array (1 , 3 , 5 , 7 ), (x : Int , y : Int ) => x > y) shouldBe res0
148
- isSorted(Array (7 , 5 , 3 , 1 ), (x : Int , y : Int ) => x < y) shouldBe res1
148
+ isSorted(Array (7 , 5 , 1 , 3 ), (x : Int , y : Int ) => x < y) shouldBe res1
149
149
isSorted(Array (" Scala" , " Exercises" ), (x : String , y : String ) => x.length > y.length) shouldBe res2
150
150
}
151
+
152
+ /**
153
+ * Currying is a transformation which converts a function `f` of two arguments into a function of one argument that
154
+ * partially applies `f`. Taking into account its signature, there's only one possible implementation that compiles.
155
+ * Take a look at it:
156
+ *
157
+ * {{{
158
+ * def curry[A,B,C](f: (A, B) => C): A => (B => C) =
159
+ * a => b => f(a, b)
160
+ * }}}
161
+ *
162
+ * Let's verify if this principle holds true in the following exercise:
163
+ */
164
+ def curryAssert (res0 : Boolean , res1 : Boolean ): Unit = {
165
+ def curry [A ,B ,C ](f : (A , B ) => C ): A => (B => C ) =
166
+ a => b => f(a, b)
167
+
168
+ def f (a : Int , b : Int ): Int = a + b
169
+ def g (a : Int )(b : Int ): Int = a + b
170
+
171
+ curry(f)(1 )(1 ) == f(1 , 1 ) shouldBe res0
172
+ curry(f)(1 )(1 ) == g(1 )(1 ) shouldBe res1
173
+
174
+ }
175
+
176
+ /**
177
+ * Uncurrying is the reverse transformation of curry. Take a look at its straightforward implementation:
178
+ * {{{
179
+ * def uncurry[A,B,C](f: A => B => C): (A, B) => C =
180
+ * (a, b) => f(a)(b)
181
+ * }}}
182
+ *
183
+ * Check by yourself if this principle holds true in the next exercise:
184
+ */
185
+ def uncurryAssert (res0 : Boolean , res1 : Boolean ): Unit = {
186
+ def uncurry [A ,B ,C ](f : A => B => C ): (A , B ) => C =
187
+ (a, b) => f(a)(b)
188
+
189
+ def f (a : Int , b : Int ): Int = a + b
190
+ def g (a : Int )(b : Int ): Int = a + b
191
+
192
+ uncurry(g)(1 , 1 ) == g(1 )(1 ) shouldBe res0
193
+ uncurry(g)(1 , 1 ) == f(1 , 1 ) shouldBe res1
194
+ }
195
+
196
+ /**
197
+ * Function composition can be implemented in the same fashion, just by following the types of its signature. In this
198
+ * case we want to feed the output of one function to the input of another function.
199
+ *
200
+ * {{{
201
+ * def compose[A,B,C](f: B => C, g: A => B): A => C =
202
+ * a => f(g(a))
203
+ * }}}
204
+ *
205
+ * Finally, let's check how this `compose` function behaves in the following exercise:
206
+ */
207
+ def composeAssert (res0 : Boolean , res1 : Int , res2 : Int ): Unit = {
208
+ def compose [A ,B ,C ](f : B => C , g : A => B ): A => C =
209
+ a => f(g(a))
210
+
211
+ def f (b : Int ): Int = b / 2
212
+ def g (a : Int ): Int = a + 2
213
+
214
+ compose(f, g)(0 ) == compose(g, f)(0 ) shouldBe res0
215
+ compose(f, g)(2 ) shouldBe res1
216
+ compose(g, f)(2 ) shouldBe res2
217
+ }
151
218
}
152
219
0 commit comments