Scala HIGHER-ORDER FUNCTIONS confuse - scala

When learning Scala, I get an example for HIGHER-ORDER FUNCTIONS, from here
https://docs.scala-lang.org/tour/higher-order-functions.html
def apply(f : Int => String, v : Int) = f(v)
def layout[A](x : A) : String = x.toString
println(apply(layout, 1000))
My question is if layout has more than 1 parameters, like this :
def layout[A](x : A, y : A) : String = x.toString + y.toString
for Intuitive understanding, I define apply as follows
def apply(f : Int, Int => String, v : Int, w : Int) = f(v, w)
Of course, this is can not compiled.
I think I have a deviation from the understanding of the type of function in Scala.
How to solve this problem with the right posture, and Solve this problem with the right posture, and more in-depth understanding of the definition of scala function types is good.

Just put a bracket around the arguments
def apply(f : (Int, Int) => String, v1 : Int, v2: Int) = f(v1, v2)
Read about Function traits in scala , there are 22 Function traits are there(Function0, Function1, .....Function2), for your case :
http://www.scala-lang.org/api/2.12.3/scala/Function2.html
Also learn about functional interface in Java8 and then try to compare with Scala Function traits.

Let me help you with an example
package scalaLearning
object higherOrderFunctions {
def main(args: Array[String]): Unit = {
def add(a: Int , b:Int):Int =a+b //Function to add integers which two int values and return and int value
def mul(a:Int, b:Int ) :Float=a*b //Function which takes two int values and return float value
def sub(a:Int,b:Int):Int=a-b //function which takes two int values and return int value
def div(a:Int,b:Int):Float =a/b//Function which takes two int value and return float value
def operation(function:(Int,Int)=>AnyVal,firstParam:Int,secondParam:Int):AnyVal=function(firstParam,secondParam) //Higher order function
println(operation(add,2,4))
println(operation(mul,2,4))
println(operation(sub,2,4))
println(operation(div,2,4))
}
}
Here while creating higher order function which takes input as function,
first you need to understand what type of of inputs your parameter functions
takes and what it returns,
In my case it takes two int values and return either float or int so you can
mention function_:(Int,Int) => AnyVal
and to pass the parameters to this function you specify
firstParam:Int(Thiscould also be firstParam:AnyVal) for the first parameter and specify
secondParam:Int(This could also be secondParam:AnyVal) for second paramter .
def operation(function(Int,Int)=>AnyVal,firstParam:Int,secondParam:Int):AnyVal=function(firstParam,secondParam) //Higher order function

Related

Infinite curryable add function

I was wondering how one would implement an infinite curried add function, for the case of explanation i would stick to scala.
I know how to prepare a simple curry like
def add(a: Int): Int => Int = {
def iadd(b: Int): Int = {
a + b
}
iadd
}
add(4)(5) // 9
How would i got about implementing add(5)(4)(x1)(x2)..(xn)
The Smart Way
The question is the comments is well-posed: when do you stop the currying and produce a result?
One solution is to stop the recursion by calling the function with zero arguments. Scala's overloading with let us do this.
add(1)(2)(3)(4)() // The () indicates that we're done currying
This is relatively straightforward. We just need a class with an apply that returns a new instance of itself
// A class with an apply method is callable like a function
class Adder(val acc: Int) {
def apply(a: Int): Adder =
new Adder(acc + a)
def apply(): Int =
acc
}
def add: Adder = new Adder(0)
println(add(1)(2)(3)(4)()) // 10
If you ever had a real reason to do this, this would be the way I would recommend. It's simple, easy to read, and adds very little boilerplate on top of the currying.
The Slightly Unhinged Way
But what fun is simple and logical? Let's get rid of those silly parentheses at the end, eh? We can do it with Scala's implicit conversions. First, we'll need to import the feature, so that Scala will stop warning us that what we're doing is silly and not a good idea.
import scala.language.implicitConversions
Then we make it so that Adder can be converted to Int
// Don't do this in real code
implicit def adderToInt(adder: Adder): Int =
adder()
Now, we don't need those parentheses at the end. We do, however, need to indicate to the type system that we want an Int.
val result: Int = add(1)(2)(3)(4)
println(result) // 10
Passing the result to a function which takes an Int, for instance, would also suffice.
Comments
Since you mentioned functional programming in general, I will note that you can do similar tricks in Haskell, using typeclasses. You can see this in action in the standard library with Text.PrintF. Note that since Haskell functions always take one argument, you'll need to have a sentinel value to indicate the "end" of the arguments (() may suffice, depending on how generic your argument types are).
If you want to reinterpret every integer n as function n.+, then just do it:
implicit class Add(val x: Int) extends AnyVal { def apply(i: Int) = x + i }
val add = 0
or even shorter (with implicit conversions):
implicit def asAdd(n: Int): Int => Int = n.+
val add = 0
Example:
add(1)(2)(3)(4) // res1: Int = 10
There is no such thing as "infinitely curryable", it's not a meaningful notion.
Well, this is not exactly infinite currying, but it gives you the something similar.
final class InfiniteCurrying[A, B] private (acc: A, op: (A, B) => A) {
final val run: A = acc
final def apply(b: B): InfiniteCurrying[A, B] =
new InfiniteCurrying(
acc = op(acc, b),
op,
)
}
object InfiniteCurrying {
def add(initial: Int): InfiniteCurrying[Int, Int] =
new InfiniteCurrying(
acc = initial,
op = (acc, b) => acc + b
)
}
import InfiniteCurrying._
val r = add(10)(20)(30)
r.run // res: Int = 60

Passing a function with default parameter to a higher order function

This maybe a very basic question. I am new to Scala. In Scala, I have a function with a default parameter value for its second parameter:
def fun(number : Int, defaultNumber : Int = 0): Int = {number + defaultNumber}
I want to have a higherOrder function to which I can pass a lowerOrder function such as the function above whose second argument has a default value. First attempt is as follows:
def higherOrder(lowerOrder : (Int, Int) => Int, number: Int) =
{lowerOrder(number)}
This obviously gives an error:
error: not enough arguments for method apply: (v1: Int, v2: Int)Int in trait Function2.
Unspecified value parameter v2.
A way around this is to get the default value in the higherOrder function:
def higherOrder(lowerOrder : (Int, Int) => Int, number: Int, defaultNumber: Int = 0) =
{lowerOrder(number, defaultNumber)}
But I don't want to do that because I may want to pass different lowerOrder functions that have different default values for their second parameter and I may not know what that default value is to pass the default value to the higherOrder function. Is there any solution for this?
Define the trait for your lower Order function.
trait Fun {
def apply(number : Int, defaultNumber : Int = 0): Int
}
Create lambda function for your lower Order function. Now you can use the function literal notation to define a Fun (note that you'll need to have started the REPL with -Xexperimental for this step to work)
val fun: Fun = { (number : Int, defaultNumber : Int) => number + defaultNumber }
Now, you can use this lambda function in your higher order function.
def higherOrder(lowerOrder : Fun, number: Int) =
{lowerOrder(number)}
Call the higher order function now.
higherOrder(fun, 10)
> result: Int = 10

what does double parameterized function means in scala?

I was going through the test code for spark. While I understand the logic behind the function given below
What does it means and What is the benefit of defining in the below syntax ?
Test Code
def withStreamingContext[R](ssc: StreamingContext)(block: StreamingContext => R): R = {
try {
block(ssc)
} finally {
try {
ssc.stop(stopSparkContext = true)
} catch {
case e: Exception =>
logError("Error stopping StreamingContext", e)
}
}
}
why does it has to be defined this way ? why can't it be
def withStreamingContext[R](ssc: StreamingContext,block: StreamingContext => R): R =
Well, it can. Separating arguments into two or more parameter lists is called currying. This way a two-parameter function can be turned into a function that takes one argument and returns a function that takes one argument and returns the result. This is what happened in the code you posted. Every n-parameter function can be seen as n 1-parameter functions (in fact, in Haskell all functions are treated like this).
Note that Scala also has a concept of partially applied functions, which boils down to the same thing. Both PAF and currying allow you to only pass a subset of parameters, thus receiving a function that takes the rest.
For example,
def sum(x: Int, y: Int) = x + y
can be curried and then you could say, for example:
def sum(x: Int)(y: Int) = x + y
def addTwo = sum(2) _ // type of addTwo is Int => Int
which gives you the same function, but with its first parameter applied. Using PAF, it would be
def sum(x: Int, y: Int) = x + y
def addTwo = sum(2, _: Int)
It is more convenient to use:
withStreamingContext(ssc) {
doSomething()
doSomethingElse()
}
vs
withStreamingContext(ssc, { doSomething(); doSomethingElse() })
First of all
def a(x: Int)(y: Int) = x * y
Is a syntactic sugar for
def a(x: Int) = (y: Int) => x * y
That means that you define a method that returns a function (closed over x)
You can invoke such method without all parameter lists and pass returned function around. You can also partially apply any other method but I think this syntax is cleaner.
Moreover, functions/methods with unary parameter lists can be invoked with expression syntax.
withStreamingContext(ssc) {
// your code block passed to function
}
This style of declaring functions is referred to as currying. It was independently introduced by Moses Schönfinkel, and then later by Haskell Curry from where it takes its name. The concept actually originates in mathematics and then introduced into computer science.
It is often conflated with partial function application; the main difference is that a call to a partially applied function returns the result immediately, not another function down the "currying" chain.
scala> def foo (x:Int, y:Int, z:Int) : Int = x + y + z
foo: (x: Int, y: Int, z: Int)Int
scala> val pa = foo(1, _:Int, _:Int)
pa: (Int, Int) => Int = <function2>
scala> pa(2,3)
res0: Int = 6
In contrast, given f:(x,y,z) -> n, currying produces f':x -> (y -> (z -> n)). In other words, applying each argument in turn to a single argument function returned by the previous invocation.
After calling f'(1), a function that takes a single argument and returns another function is returned, not a function that takes two arguments.
In contrast partial function application refers to the process of fixing a number of arguments to a function, producing another function of smaller arity. These two are often conflated.
The benefits/advantages of currying have already been mentioned elsewhere. The main issue you had was understanding the syntax and it's origins which has been explained.

Parameter list VS returned function

I've been experimenting with Scala. I am trying to understand implicits and came across this situation.
Is behaviour of parameter b same for both functions?
Are paramareters list just syntax sugar over returning function?
My experiments show, they behave the same.
Thanks
implicit val v = 2
// 1.
def testB(a: Int)(b: Int)(implicit i: Int): Int = {
println(a + b + i)
11
}
println(testB(7)(8))
println(testB(7) {
8
})
// 2.
def testC(a: Int): (Int) => Int = {
def innerTest2C(b: Int)(implicit i: Int) = {
println(a + b + i)
11
}
innerTest2C
}
println(testC(7)(8))
println(testC(7) {
8
})
The rule is that whenever a function takes exactly one parameter, you can replace the normal brackets () with curly brackets {}. Curly brackets define a block and allow you to place several statements inside it. The block will evaluate to the value of the expression in the last line like in all blocks.
In 2., the function testC returns another function from Int to Int, so you cann call the result of testC(7) again with one parameter: testC(7)(x). If you just consider the println statements, there is nothing different here.
What you need to understand is that
def testB(a: Int)(b: Int)
is different from
def testB(a: Int, b: Int)
insofar that the former represents two functions like in your second case. You can call testB(x) and will obtain another function from Int to Int. Applying only part of the paramters of a function in order to obtain another function is called currying.

Scala, Composing Function with two values

def adder(a:Int,b:Int):Int = {a+b}
def doubler(a:Int):Int = {a*2}
def doubleAdd = doubler _ compose adder
I get the error: type mismatch
found: (Int,Int)=>Int
required: ? => Int
Then if I just try doubleAdd = doubler(adder _) I get the same error except required Int instead of ? => Int
Is there a way of composing a function with two parameters? Sorry if this is pretty basic, I'm pretty new to the language, and I couldn't find an example with two parameters anywhere.
You're attempting to compose a Function2 (adder) with a Function1, hence the issue. One workaround is to change your definition of Adder to a curried version:
def adder(a: Int)(b: Int):Int = a + b
Then doubleAdd to partially apply adder like this:
def doubleAdd(x: Int) = doubler _ compose adder(x)
What's happening under the hood is transforming adder from a Function2 (Int, Int) => Int, to a Function1 (Int) => (Int) => Int, or a function that returns a function. You're then able to compose the function returned from adder with the first parameter already applied.