Can someone explain the scala code below? - scala

scala> def lift3[A,B,C,D] (
| f: Function3[A,B,C,D]): Function3[Option[A], Option[B], Option[C], Option
[D]] = {
| (oa: Option[A], ob:Option[B], oc: Option[C]) =>
| for(a <- oa; b <- ob; c <- oc) yield f(a,b,c)
| }
lift3: [A, B, C, D](f: (A, B, C) => D)(Option[A], Option[B], Option[C]) => Option[D]
In particular, the following line:
def lift3[A,B,C,D] (
f: Function3[A,B,C,D]): Function3[Option[A], Option[B], Option[C], Option
[D]]
This is taken from the book Scala In Depth by Joshua D Suereth (Listing 2.1, chapter 2). I'm not sure what purpose the additional Option[D] serves. In the body of the function, the code only maps to the first three parameters to the output type D. When then, D is declared in the input parameter list? Am I missing something?
With my limited understanding, I would read the function declaration as a function that takes a function as a parameter (which in turn takes 4 parameters) and returns a function that takes 4 parameters. Also, why is there no mention of the return type?
Thanks in advance!

With my limited understanding, I would read the function declaration as a function that takes a function as a parameter (which in turn takes 4 parameters) and returns a function that takes 4 parameters. Also, why is there no mention of the return type?
Function3[A,B,C,D] is a function with 3 parameters (of types A, B and C) and D is the return type (it can also be written as (A, B, C) => D; this is exactly the same type). So in Function3[Option[A], Option[B], Option[C], Option[D]], Option[D] is the return type, not a parameter type.

A function3 takes 3 parameters. The D is the return type of the function. What the code does, is take a function with 3 arguments and return a function with 3 arguments, where each argument and its return type is "lifted" to an Option.
You can check out the API docs for Function3 here.
And an explanation for the R generic type can be found in the docs for Function2

Related

Scala - Rule to infer the variable on the right hand side

I tried to do research but still not yet figure out what is the terminology of Scala, related to lower case a,b as per the code below
def curry[A, B, C](f: (A, B) => C): A => (B => C) = a => b => f(a, b)
Why is that a,b appears on the right hand side?
I know that it is a part of Algebraic Data Type but still could not find a match definition for this.
Update based on Tim's answer, "Scala knows the type of a and b from the return type A => (B => C). a is type A, b is type B."
I want to ask about how Scala knows the type of a and b, i.e: the mechanism behind? What is the terminology of this?
I guess this is a language feature. Please suggest a foundation guideline to fully understand and practice to gain intuition when reading these complex code.
Update from Mario Galic's comment: ... Scala compiler can perform type inference based on the signature of curry ... Please clarify: if the left hand side (i.e the signature) is too obvious, why we need to have the right hand side definition? I mean, there is only 1 way to infer the logic of the left hand side, then, what is the need of creating the right hand side content?
P/S: I wish that I could mark each feedback as the answer because each provides different aspect which helps me to fully grasp the meaning.
It might help to add full type annotations
def curry[A, B, C](f: (A, B) => C): A => (B => C) =
(a: A) => ((b: B) => f(a, b): C)
Note how curry is a method that takes a function as input and also returns a function as output. You might be wondering where do a and b come from in the output function
(a: A) => ((b: B) => f(a, b): C)
but note that they are just the means of declaring the parameters of the output function. You are free to give them any name, for example the following would also work
(x: A) => ((y: B) => f(x, y): C)
The key is to understand that functions are first class values in Scala, so you can pass them in as arguments to other functions and return them as return values from other functions, in the same way you would do with familiar values like say integer 42. Writing value 42 is straightforward, but writing down function value is more verbose since you have to specify the parameters like a and b but nevertheless conceptually it is still just a value. Hence we could say curry is a method that takes a value and returns a value, but these values happen to be function values.
As we all know, it's pretty easy to create a tuple: (1,'a'). And the type of said tuple is pretty simple: (Int,Char). That type designation, however, is a convenient alternative for the more verbose type designation Tuple2[Int,Char]. In fact, the tuple creation itself is a convenient alternate syntax to the more direct new Tuple2(1,'a').
It's a similar story with functions.
The type designation Char => Int is a convenient alternative to the more verbose Function1[Char,Int]. And, after studying the ScalaDocs page, we learn that a simple function like...
val ctoi = (c:Char) => c.toInt
...is the equivalent of...
val ctoi = new Function1[Char, Int] {
def apply(c: Char): Int = c.toInt
}
So, armed with this information, we can now translate...
def curry[A,B,C](f: (A, B) => C): A => (B => C) =
a => b => f(a, b)
...into its equivalent...
def curry[A,B,C](f: Function2[A,B,C]): Function1[A,Function1[B,C]] =
new Function1[A,Function1[B,C]] {
def apply(a:A) = new Function1[B,C] {def apply(b:B) = f(a,b)}
}
With this it's a little easier to see how a => b => ..., while a bit confusing at first, is actually a very convenient way to designate the names of the arguments being passed in to the hidden apply() methods.
The question doesn't really make sense, but in case this helps here is a breakdown of that line:
def curry[A, B, C](f: (A, B) => C): A => (B => C) = a => b => f(a, b)
This splits into a definition and an implementation with = inbetween. The definition is
def curry[A, B, C](f: (A, B) => C): A => (B => C)
Breaking it down further, A, B, and C are type parameters, meaning that any three types can be used when calling this function.
Next comes the single argument to the function:
f: (A, B) => C
The value of this argument is a function that takes two values (one of type A and one of type B) are returns a single value of type C.
Next comes the type of the result:
A => (B => C)
This is a function that takes a single argument of type A and returns a function that takes a single argument of type B and returns a result of type C.
So curry is a function that takes a function of type (A, B) => C) and returns a function of type A => (B => C). This implements the process known as currying (hence the name).
Now for the implementation (the other side of the =):
a => b => f(a, b)
Adding some brackets might make this clearer:
a => (b => f(a, b))
This is a function that take a and returns b => f(a, b). a is the argument for this function. So that leaves this
b => f(a, b)
This is a simple function with an argument b that returns f(a, b).
Scala knows the type of a and b from the return type A => (B => C). a is type A, b is type B.

Scala: how do I understand the curry mechanism

I understand how does a curried function work in practice.
def plainSum(a: Int)(b: Int) = a + b
val plusOne = plainSum(1) _
where plusOne is a curried function of type (Int) => Int, which can be applied to an Int:
plusOne(10)
res0: Int = 11
Independently, when reading the book (Chapter 2) Functional Programming in Scala, by Chiusano and Bjarnason, it demonstrated that the implementation of currying a function f of two arguments into a function of one argument can be written in the following way:
def curry[A, B, C](f: (A, B) => C): A => (B => C) =
a: A => b: B => f(a, b)
Reference: https://github.com/fpinscala/fpinscala/blob/master/answers/src/main/scala/fpinscala/gettingstarted/GettingStarted.scala#L157-L158
I can understand the above implementation, but have a hard time associating the signature with the plainSum and plusOne example.
The 1 in the plainSum(1) _ seems to correspond to the type parameter A, and the function value plusOne seems to correspond to the function signature B => C.
How does the Scala compiler apply the above curry signature when seeing the statement plainSum(1) _?
You are conflating partially applying a function with currying. In Scala, they some differences:
A partially applied function passes less arguments than provided in the application with the rest of the arguments, represented by the placeholder(_), is partially applied on the next call.
Currying is when a higher order function takes a function of N arguments and transforms it into a one-arg chains of functions.
The plusOne example is naturally curried out of the box by virtue of the multi-parameter list which takes a function of one argument successively and return the last argument.
Your mistake is that you are trying to use currying twice when this notation()() already gives you currying.
Meanwhile you can achieve same effect by currying the plainSum signature to the curry function like so:
def curry[A, B, C](f: (A, B) => C): A => (B => C) =
(a: A) => (b: B) => f(a, b)
def plainSum(a: Int, b: Int) = a + b
val curriedSum = curry(plainSum)
val add2 = curriedSum(2)
add2(3)
Both(partial application and currying) shouldn't be confused with another concept called partial functions.
Note: The red book, fpinscala, tried creating those abstraction as done in the Scala library without the syntactic sugar.

Testing a generated curried function with Scala Test

I'm having hard times trying to create a Scala Test to checks this function:
def curry[A,B,C](f: (A,B) => C): A => (B => C) =
a => b => f(a,b)
The first thought I had was to validate if given a function fx passed into curry(fx) function, will return a curried version of it.
Any tips?
One way to test it, is to pass different f's to it and see if you are getting back the function you expect. For example, you can test an f that returns the arguments as a tuple:
def f(x: String, y: Int) = (x, y)
curry(f)("4")(7) must be(("4", 7))
IMO, testing it for a few different functions f and for a few different a and b would be more than sufficiently assuring that something as trivial as this works as intended.

Difference between f(a,b) and f(a)(b) in Scala

I am very very new to Scala. I am reading a book called functional programming in scala by Paul Chiusano and Rúnar Bjarnason. So far I am finding it interesting. I see a solution for curry and uncurry
def curry[A,B,C](f: (A, B) => C): A => (B => C)= {
a => b => f(a,b)
}
def uncurry[A,B,C](f: A => B => C): (A, B) => C = {
(a,b) => f(a)(b)
}
In Curry I understand f(a,b) which results in value of type C but in uncurry I do not understand f(a)(b). Can anyone please tell me how to read f(a)(b) or how is this resulting to a type of C or please refer me some online material that can explain this to me?
Thanks for your help.
Basically the return type of f(a) is a function of type B => C lets call this result g.
If you then call g(b) you obtain a value of type C.
f(a)(b) can be expanded to f.apply(a).apply(b)
In the uncurry method you take a so-called "curried" function, meaning that instead of having a function that evaluates n arguments, you have n functions evaluating one argument, each returning a new function until you evaluate the final one.
Currying without a specific support from the language mean you have to do something like this:
// curriedSum is a function that takes an integer,
// which returns a function that takes an integer
// and returns the sum of the two
def curriedSum(a: Int): Int => Int =
b => a + b
Scala however provides further support for currying, allowing you to write this:
def curriedSum(a: Int)(b: Int): Int = a + b
In both cases, you can partially apply curriedSum, getting a function that takes an integer and sums it to the number you passed in originally, like this:
val sumTwo: Int => Int = curriedSum(2)
val four = sumTwo(2) // four equals 4
Let's go back to your case: as we mentioned, uncurry takes a curried function and turns it into a regular function, meaning that
f(a)(b)
can read as: "apply parameter a to the function f, then take the resulting function and apply the parameter b to it".
In case if somebody is looking for an explanation. This link explains it better
def add(x:Int, y:Int) = x + y
add(1, 2) // 3
add(7, 3) // 10
After currying
def add(x:Int) = (y:Int) => x + y
add(1)(2) // 3
add(7)(3) // 10
In the first sample, the add method takes two parameters and returns the result of adding the two. The second sample redefines the add method so that it takes only a single Int as a parameter and returns a functional (closure) as a result. Our driver code then calls this functional, passing the second “parameter”. This functional computes the value and returns the final result.

Scala Function.tupled and Function.untupled equivalent for variable arity, or, calling variable arity function with tuple

I was trying to do some stuff last night around accepting and calling a generic function (i.e. the type is known at the call site, but potentially varies across call sites, so the definition should be generic across arities).
For example, suppose I have a function f: (A, B, C, ...) => Z. (There are actually many such fs, which I do not know in advance, and so I cannot fix the types nor count of A, B, C, ..., Z.)
I'm trying to achieve the following.
How do I call f generically with an instance of (A, B, C, ...)? If the signature of f were known in advance, then I could do something involving Function.tupled f or equivalent.
How do I define another function or method (for example, some object's apply method) with the same signature as f? That is to say, how do I define a g for which g(a, b, c, ...) type checks if and only if f(a, b, c, ...) type checks? I was looking into Shapeless's HList for this. From what I can tell so far, HList at least solves the "representing an arbitrary arity args list" issue, and also, Shapeless would solve the conversion to and from tuple issue. However, I'm still not sure I understand how this would fit in with a function of generic arity, if at all.
How do I define another function or method with a related type signature to f? The biggest example that comes to mind now is some h: (A, B, C, ...) => SomeErrorThing[Z] \/ Z.
I remember watching a conference presentation on Shapeless some time ago. While the presenter did not explicitly demonstrate these things, what they did demonstrate (various techniques around abstracting/genericizing tuples vs HLists) would lead me to believe that similar things as the above are possible with the same tools.
Thanks in advance!
Yes, Shapeless can absolutely help you here. Suppose for example that we want to take a function of arbitrary arity and turn it into a function of the same arity but with the return type wrapped in Option (I think this will hit all three points of your question).
To keep things simple I'll just say the Option is always Some. This takes a pretty dense four lines:
import shapeless._, ops.function._
def wrap[F, I <: HList, O](f: F)(implicit
ftp: FnToProduct.Aux[F, I => O],
ffp: FnFromProduct[I => Option[O]]
): ffp.Out = ffp(i => Some(ftp(f)(i)))
We can show that it works:
scala> wrap((i: Int) => i + 1)
res0: Int => Option[Int] = <function1>
scala> wrap((i: Int, s: String, t: String) => (s * i) + t)
res1: (Int, String, String) => Option[String] = <function3>
scala> res1(3, "foo", "bar")
res2: Option[String] = Some(foofoofoobar)
Note the appropriate static return types. Now for how it works:
The FnToProduct type class provides evidence that some type F is a FunctionN (for some N) that can be converted into a function from some HList to the original output type. The HList function (a Function1, to be precise) is the Out type member of the instance, or the second type parameter of the FnToProduct.Aux helper.
FnFromProduct does the reverse—it's evidence that some F is a Function1 from an HList to some output type that can be converted into a function of some arity to that output type.
In our wrap method, we use FnToProduct.Aux to constrain the Out of the FnToProduct instance for F in such a way that we can refer to the HList parameter list and the O result type in the type of our FnFromProduct instance. The implementation is then pretty straightforward—we just apply the instances in the appropriate places.
This may all seem very complicated, but once you've worked with this kind of generic programming in Scala for a while it becomes more or less intuitive, and we'd of course be happy to answer more specific questions about your use case.