Scala - understanding a code snippet involving currying - scala

I'm new to scala and I'm having a little trouble understanding currying - I'm practicing by coding simple functions for now, and would need clarification about the following
def mul (a: Int) (b: Int): Int =
{
{
a * b
}
}
Is the above function definition same as the below?
def mul: Int => Int => Int = {
(a: Int) =>
{
(b: Int) =>
a * b
}
}
From syntax I could interpret mul as a function that accepts an integer, and returns a function that accepts an integer and returns an integer. But I'm not sure if my interpretation is actually correct. Any explanation regarding the above example or the syntax of curried functions will be really helpful.

Your interpretation is correct. But you don't need all those braces.
def mul(a: Int)(b: Int) = a*b
val mulAB = (a: Int) => { (b: Int) => a*b } // Same as mul _
val mul5B = (b: Int) => 5*b // Same as mulAb(5) or mul(5) _
In general, you can rewrite any function with multiple arguments as a curried chain instead, where each argument produces a function that takes one fewer arguments until the last one actually produces the value:
f(a: A ,b: B ,c: C, d: D): E <===> A => B => C => D => E
In Scala, the natural grouping is by parameter block, not by individual parameter, so
f(a: A)(b: B, c: C)(d: D): E <===> A => (B,C) => D => E

Related

is it possible to implement flip as a Scala function (and not a method)

As a part of learning Scala I try to implement Haskell's flip function (a function with signature (A => B => C) => (B => A => C)) in Scala - and implement it as a function (using val) and not as a method (using def).
I can implement it as a method, for instance this way:
def flip[A, B, C](f: (A, B) => C):((B, A) => C) = (b: B, a: A) => f(a, b)
val minus = (a: Int, b: Int) => a - b
val f = flip(minus)
println(f(3, 5))
However, when I try to implement it as a function, it does not work:
val flip = (f: ((Any, Any) => Any)) => ((a: Any, b: Any) => f(b, a))
val minus = (a: Int, b: Int) => a - b
val f = flip(minus)
println(f(3, 5))
When I try to compile this code, it fails with this message:
Error:(8, 18) type mismatch;
found : (Int, Int) => Int
required: (Any, Any) => Any
val f = flip(minus)
I understand why it fails: I try to pass (Int, Int) => Int where (Any, Any) => Any is expected. However, I don't know how to fix this problem. Is it possible at all?
Scala doesn't support polymorphic functions, unlike methods which are. This is due to the first class value nature of functions, which are simply instances of the FunctioN traits. These functions are classes, and they need the types to be bound at declaration site.
If we took the flip method and tried to eta expand it to a function, we'd see:
val flipFn = flip _
We'd get back in return a value of type:
((Nothing, Nothing) => Nothing) => (Nothing, Nothing) => Nothing
Due to the fact that none of the types were bound, hence the compiler resorts to the buttom type Nothing.
However, not all hope is lost. There is a library called shapeless which does allow us to define polymorphic functions via PolyN.
We can implement flip like this:
import shapeless.Poly1
object flip extends Poly1 {
implicit def genericCase[A, B, C] = at[(A, B) => C](f => (b: B, a: A) => f(a, b))
}
flip is no different from the FunctionN trait, it defines an apply method which will be called.
We use it like this:
def main(args: Array[String]): Unit = {
val minus = (a: Int, b: Int) => a - b
val f = flip(minus)
println(f(3, 5))
}
Yielding:
2
This would also work for String:
def main(args: Array[String]): Unit = {
val stringConcat = (a: String, b: String) => a + b
val f = flip(stringConcat)
println(f("hello", "world"))
}
Yielding:
worldhello

How is this exactly a curried function?

I am reading Functional Programming in Scala, and going through different exericses. I encountered currying.
Can someone explain to me this curried function and how does this work? I can seem to understand this piece of code. compared to the ones I saw on different blogs regarding currying in Scala.
def curry[A,B,C](f: (A, B) => C): A => (B => C) = a => b => f(a,b)
is a from a => b => f(a,b) a function if so what are its arguments?
Also update what does this mean? a in a => b => f(a,b) means? is a function that will return a function named b that takes single parameter and will return a function?
I'll assume you understand the concept of currying and that the type definition makes sense to you: A => B => C.
The implementation is: a => b => f(a,b), you could read it as:
... = { a =>
{ b =>
{ f(a,b) }
}
}
So a is the parameter accepted as input of your function of type A => (B => C). And this function returns a second function - of type B => C, that takes b:B and apply f to both.
Edit: you could use this very verbose version if it helps you understand:
def curry[A,B,C](f: (A, B) => C): A => (B => C) = {
def aToBToC(a: A): B => C = {
def bToC(b: B): C = {
f(a,b)
}
bToC
}
aToBToC
}
See how I define private functions in nested scopes? (I haven't tried in the REPL, maybe there is a typo, but you get the idea.)
You defined a function curry which takes an another function as parameter. The return type of that function is A => (B => C), also a function from A to B => C.
After that you defined a implementation of A => (B => C), also for given a return a function b => f(a,b).
Example:
def plus(a: Int, b:Int): Int = a + b
The curried version of plus:
scala> def plusC(a:Int): Int => Int = plus(a, _)
plusC: (a: Int)Int => Int
scala> plusC(1)
res4: Int => Int = <function1>
scala> res4(10)
res5: Int = 11
This is not a curried function. This is a curry method (note: function and methods are very distinct concepts in Scala), i.e. a method that does the currying. Its return value is a curried function; it takes in a function of two arguments and returns a curried function.
def curry[A,B,C] is not curried function itself, it just shows how to convert function that takes two parameters f: (A, B) => C into the curried function A => (B => C). a => b => f(a, b) means that function takes parameter a and returns function b => f(a, b), which in its turn returns final value f(a, b).

How to execute user-defined function that accepts and returns another?

Here's my function:
def partial1[A, B, C](a: A, f: (A, B) => C): B => C = (b: B) => f(a, b)
> partial1: [A, B, C](a: A, f: (A, B) => C)B => C
Here I invoke the function partial1:
def fun(a: Int, b: Int) = a + b
> fun: (a: Int, b: Int)Int
val r = partial1(1, fun)
> r : Int => Int = <function1>
r(fun(1,3))
> res0: Int = 5
So r is a function which takes a function as parameter and returns a Function1 (a function with 1 parameter). Should Int => Int not be Int, Int since two Ints are the function parameters?
Why can't I implement Partial1 like partial1(1,(fun(1,3))) which causes compiler error : type mismatch; found : Int required: (?, ?) => ? ?
First of all, partial1 isn't a partial function. It's a function that returns another function so it's a higher-order function.
The compile error you're getting is because partial1 expects a function (A, B) => C, but you're passing fun(1,3), which evaluates to an Int. And Int is not the same as (Int, Int) => Int.
class ex03 {
def partial1[A,B,C](a:A, f:(A,B) => C): B => C = f(a,_)
}
class ex03Test extends UnitSpec {
behavior of "partial1"
it should "return 6" in {
val e = new ex03
val multiplyByTwo = e.partial1(2, (a:Int, b:Int) => a * b)
multiplyByTwo(3) mustBe 6
}}

How to set type parameter bound in scala to make generic function for numerics?

I want to make a sum function that works with all Numeric types.
This works:
object session {
def mapReduce[A](f: A => A, combine: (A, A) => A, zero: A, inc: A)
(a: A,b: A)
(implicit num:Numeric[A]): A = {
def loop(acc: A, a: A) =
if (num.gt(a, b)) acc
else combine(f(a), mapReduce(f, combine, zero, inc)(num.plus(a, inc), b))
loop(zero, a)
}
def sum(f: Int => Int)
(a: Int, b: Int) : Int = {
mapReduce(f, (x: Int, y: Int) => x + y, 0, 1)(a, b)}
sum(x => x)(3, 4) //> res0: Int = 7
def product(f: Int => Int)
(a: Int, b: Int): Int = {
mapReduce(f, (x: Int, y: Int) => x * y, 1, 1)(a, b)}
product(x => x)(3, 4) //> res1: Int = 12
def fact(n: Int) = product(x => x)(1, n)
fact(5) //> res3: Int = 120
}
but when I try to make sum generic like this:
def sum[A](f: A => A)
(a: A, b: A)
(implicit num:Numeric[A]): A = {
mapReduce(f, (x: A, y: A) => num.plus(x, y), 0, 1)(a, b)}
sum(x => x)(3.0, 4.0) // should be 12.0
I get this error on f
type mismatch; found : A => A required: Any => Any
when i pass it to mapReduce. So what do i need to do to make sum accept any Numeric value?
If I'm not mistaken, the other answer is almost correct except for the fact that the type has to be made explicit when calling mapReduce instead of when calling sum.
So in your generic definition of sum, you might want to do this:
def sum[A](f: A => A)(a: A, b: A)(implicit num: Numeric[A]): A =
mapReduce[A](f, num.plus, num.zero, num.one)(a, b)
That's however not enough for the typer to infer the concrete type of A, e.g. Double when calling sum(x => x)(3.0, 4.0). The reason for this is that the typer is going from first to last parameter list, left to right.
Your first parameter list declares f: A => A and only the second parameter list defines (a: A, b: A). Once the typer reaches the end of the first parameter list, it doesn't know what A exactly is, and hence it fixes the type of A to some "abstract" A. The only thing that it knows about A at this point is that it is a subtype of Any.
When the typer then gets to the second parameter list, it could theoretically infer A as Double or whatever your concrete type is, but as said before the type has already been fixed. This is just a flaw of Scala's typer which can easily be circumvented once you get the hang of it.
More precisely, all you have to do is help the typer by switching the first and second parameter lists like so:
def sum[A](a: A, b: A)(f: A => A)(implicit num: Numeric[A]): A =
mapReduce[A](f, num.plus, num.zero, num.one)(a, b)
Then it's possible to call sum without being explicit about the type, e.g.
Console println sum(3.0, 4.0)(x => x) // 7.0
Give the type of sum explicitly. I have already provided an answer to a similar question in
A simple foldRight type issue in Scala.
Questions are totally different but the reason is exactly the same.

How does the type inferencer work on reduceLeft?

Further to my other question about reduceLeft, the signature of reduceLeft on Seq is
def reduceLeft [B >: A] (f: (B, A) ⇒ B): B
and we can call it with expressions such as
List(1,2,3,4) reduceLeft (_ + _)
In this example A is Int, so reduceLeft expects a Function2[B >: Int, Int, B]. Regardless of how reduceLeft works (which is irrelevant), how does the type inferencer know that B has a + method, when it could be of type Any?
I think the section 6.26.4 Local Type Inference of the spec sort of explains what's going on. The compiler will look for an optimal type. When the type parameter is contravariant the type chosen will be maximal (in this case Any) and otherwise (invariant or covariant) minimal (in this case Int).
There are a couple examples which I can't really relate to reduceLeft.
What I did notice is the inference seems to happen before looking at the anonymous function passed:
scala> List(1,2).reduceLeft[Any](_.toString + _)
res26: Any = 12
But If I don't help the type inferencer:
scala> List(1,2).reduceLeft(_.toString + _)
<console>:8: error: type mismatch;
found : java.lang.String
required: Int
List(1,2).reduceLeft(_.toString + _)
Edit, I'm wrong the anonymous function is taken into account, this works:
List(1,2).reduceLeft((_:Any).toString + (_:Any).toString)
There is a compiler -Ytyper-debug option that you can run on:
List(1,2).reduceLeft(_+_)
It will show you that somehow the compiler assumes the expected type of the anonymous function is (Int, Int) => Int, then it proceeds to check the _ + _ against it and succeeds and then infers B as Int. Snippet here:
typed immutable.this.List.apply[Int](1, 2).reduceLeft: [B >: Int](f: (B, Int) => B)B
adapted immutable.this.List.apply[Int](1, 2).reduceLeft: [B >: Int](f: (B, Int) => B)B to ?, undetparams=type B
typing ((x$1, x$2) => x$1.$plus(x$2)): pt = (Int, Int) => Int: undetparams=,
// some time later
typed ((x$1: Int, x$2: Int) => x$1.+(x$2)): (Int, Int) => Int
adapted ((x$1: Int, x$2: Int) => x$1.+(x$2)): (Int, Int) => Int to (Int, Int) => Int,
typed immutable.this.List.apply[Int](1, 2).reduceLeft[Int](((x$1: Int, x$2: Int) => x$1.+(x$2))): Int
I don't know why in absence of type ascription the anonymous function is assumed to be (Int, Int) => Int.
If B >: X and the compiler knows X but cannot resolve B it simply assumes B = X.
It is somewhat practical since it only has two options for B and only one is known. So absent knowing which super class it assumes that B is X. You can test the compilers decision making process with the following code.
class Y {
def bar(y:Y) = this
}
case class X( i: Int ) extends Y {
def foo(x:X)=X(i+x.i)
}
val t = new Y bar X(7)
val t2 = X(8) bar X(7)
val res = List(X(1),X(2),X(3)) reduceLeft { _ foo _ }
val res2 = List(X(1),X(2),X(3)) reduceLeft { _ bar _ } // will not compile