How to compose curried functions in Scala - scala

Is it possible compose functions in Scala that are curried? For example:
def a(s1: String)(s2: String): Int = s1.length + s2.length
def b(n: Int): Boolean = n % 2 == 0
def x : String => String => Boolean = a andThen b
x("blabla")("foo")
Edit :
I've found a way of doing it in Haskell :
a :: String -> String -> Int
a s1 s2 = length s1 + length s2
b :: Int -> Bool
b n = mod n 2 == 0
c :: String -> String -> Bool
c = curry (b . (uncurry a))

This should work:
def x = a _ andThen (_ andThen b)
The first _ avoids invoking a and makes it into a function value. This value is of type String=>String=>Int, i.e. a function that takes String and returns String=>Int.
The argument to the andThen method is a function that takes the result of the original function and modifies it. So in this case it requires a function that takes String=>Int and returns a new value, a function String=>Boolean. We can fabricate this new function by using andThen on the original function. This takes the result of a and composes it with the new function b.

Related

How to declare in scala a default param in a method of an implicit class

In order to use infix notation, I have the following example of scala code.
implicit class myclass(n:Int ){
private def mapCombineReduce(map : Int => Double, combine: (Double,Double) => Double, zero: Double )(a:Int, b:Double): Double =
if( a > b) zero else combine ( map(a), mapCombineReduce(map,combine,zero)(a+1,b) )
var default_value_of_z : Int = 0
def sum( z : Int = default_value_of_z) = mapReduce( x=>x , (x,y) => x+y+z, 0)(1,n)
def ! = mapCombineReduce( x=> x, (x,y) => x*y, 1)(1,n)
}
4 !
4 sum 1 //sum the elements from 1 to 7 and each time combine the result, add 1 to the result.
4 sum
Is there any way in scala 2.12 to run 4 sum without have a double declaration of the sum method inside myclass ?
No, because default arguments are only used if argument list is provided
def f(x: Int = 1) = x
f // interpreted as trying to do eta-expansion
In fact starting Scala 3 it will indeed eta-expand
scala> def f(x: Int = 1) = x
def f(x: Int): Int
scala> f
val res1: Int => Int = Lambda$7473/1229666909#61a1990e
so in your case you will have to write 4.sum() with argument list present.

Scala function composition totalFn(partialFn(totalFn(x)))

I was trying to compose three functions with only the middle one being a PartialFunction. I would expect the resulting type to be PartialFunction as well.
Example:
val mod10: Int => Int = _ % 10
val inverse: PartialFunction[Int, Double] = { case n if n != 0 => 1.0 / n }
val triple: Double => Double = _ * 3
val calc: Int => Double = mod10 andThen inverse andThen triple
However, calc is not defined on the whole of its domain. It will throw MatchError for every number divisible by 10.
What is the reason for returning a total function when at least one of the functions in the composition is partial?
Another example where composition of partial functions results in another partial function with incorrect domain conditions:
val inverse: PartialFunction[Double, Double] = { case n if n != 0 => 1.0 / n }
val arcSin: PartialFunction[Double, Double] = {
case n if math.abs(n) <= 1 => math.asin(n)
}
val calc: PartialFunction[Double, Double] = inverse andThen arcSin
I would expect the domain of calc to be (-Infinity, -1] union [1, Infinity) but calling calc.lift(0.5) will throw a MathError instead of returning None because the input is within the first function's domain.
Thanks,
Norbert
Example 1: What is the reason for returning a total function when at least one of the functions in the composition is partial?
It's because the first function in your first example is a total function (Function1) and its andThen method returns a Function1 regardless of whether the second function is total or partial:
def andThen[A](g: (R) => A): (T1) => A
My guess is that the Scala language design team prefers a more generalized returned value since PartialFunction is a subclass of Function and would rather let users derive specialized code as needed.
Example 2: calling calc.lift(0.5) will throw a MathError instead of returning None
From the PartialFunction API doc, composing two partial functions via andThen will return a partial function with the same domain as the first partial function:
def andThen[C](k: (B) => C): PartialFunction[A, C]
Thus, the resultant composed function disregards the fact that inverse(0.5) (i.e. 2.0) is outside the domain of the second partial function arcSin.
So, when composing a function (total or partial) with a partial function using andThen, how can we make it return a partial function with proper domain?
Similar to what's demonstrated in this SO Q&A, one can enhance andThen via a couple of implicit classes to restrict the domain of the resultant composed function to a subset of the first function's domain that return values within the partial function's domain:
object ComposeFcnOps {
implicit class TotalCompose[A, B](f: Function[A, B]) {
def andThenPartial[C](that: PartialFunction[B, C]): PartialFunction[A, C] =
Function.unlift(x => Option(f(x)).flatMap(that.lift))
}
implicit class PartialCompose[A, B](pf: PartialFunction[A, B]) {
def andThenPartial[C](that: PartialFunction[B, C]): PartialFunction[A, C] =
Function.unlift(x => pf.lift(x).flatMap(that.lift))
}
}
Testing with the example functions:
import ComposeFcnOps._
val mod10: Int => Int = _ % 10
val inverse1: PartialFunction[Int, Double] = { case n if n != 0 => 1.0 / n }
val triple: Double => Double = _ * 3
val calc1 = mod10 andThenPartial inverse1 andThen triple
// calc1: PartialFunction[Int,Double] = <function1>
calc1.isDefinedAt(0)
// res1: Boolean = false
val inverse2: PartialFunction[Double, Double] = { case n if n != 0 => 1.0 / n }
val arcSin: PartialFunction[Double, Double] = {
case n if math.abs(n) <= 1 => math.asin(n)
}
val calc2 = inverse2 andThenPartial arcSin
// calc2: PartialFunction[Double,Double] = <function1>
calc2.isDefinedAt(0.5)
// res2: Boolean = false
calc2.lift(0.5)
// res3: Option[Double] = None
I think the error is your only expecting non-zero value.
{ case n if n != 0 => 1.0 / n }
then what if it will equal to zero then that is the cause of match Error..
{
case n if n != 0 => 1.0 / n // non-zero value.
case n if n == 0 => // zero value.
}
Hope it helps.
andThen is defined on Function1, and simply isn't designed to compose partial functions. Therefore, I recommend lifting them to total functions before using it.
val calc = Function.unlift(mod10 andThen inverse.lift andThen (_.map(triple)))
And
val calc = Function.unlift(inverse.lift andThen (_.flatMap(arcSin.lift)))

Scala function definition vs application

Why does f in the following code snippet gives the value of 1. I was expected f() to be 1. How can I obtain a reference to the function f:()=> Int
var y = 0
def f():Int = {y + 1}
f
Somethings in scala drive me nuts.
If you're calling a function that has no parameters, then you can drop the brackets. That's why f evaluates to 1.
The exact same expression can also evaluate into a function reference if the compiler knows that you're expecting a value of that type.
val foo: () => Int = f
You can obtain so using _ :
var y = 0
def m:Int = {y + 1}
val result = m _ // type of result is an instance of Function0 "() => Int"
Use _ when compiler is not expecting Function object.
If you want f to be an expression of type () => Int that evaluates to { y + 1 }, then just define it as such:
var y = 0
val f: () => Int = () => { y + 1 }
Now
f
does nothing (it just gives back the lambda of type () => Int), but
f()
gives 1.
You don't really need the type ascription, this works too:
val f = () => { y + 1 }

Why is this function called multiple times?

In this function "f" :
def f(x: => Int) : Int = x * x * x //> f: (x: => Int)Int
var y = 0 //> y : Int = 0
f {
y += 1
println("invoked")
y
} //> invoked
//| invoked
//| invoked
//| res0: Int = 6
"f" is invoked same amount of times as "x" parameter is multiplied.
But why is function invoked multiple times ?
Should "f" not expand to 1 * 1 * 1 not 1 * 2 * 3 ?
Your x is not a function, it is a by-name parameter, and its type is a parameterless method type.
Parameterless method type means the same as def x, something that is evaluated every time you reference it. By reference, we mean x and not x.apply() or x().
The expression you're passing to your function f is evaluated every time x is referenced in f. That expression is the whole thing in braces, a block expression. A block is a sequence of statements followed by the result expression at the end.
Here's another explanation: https://stackoverflow.com/a/13337382/1296806
But let's not call it a function, even if it behaves like one under the covers.
Here is the language used in the spec:
http://www.scala-lang.org/files/archive/spec/2.11/04-basic-declarations-and-definitions.html#by-name-parameters
It's not a value type because you can't write val i: => Int.
It was a big deal when they changed the implementation so you could pass a by-name arg to another method without evaluating it first. There was never a question that you can pass function values around like that. For example:
scala> def k(y: => Int) = 8
k: (y: => Int)Int
scala> def f(x: => Int) = k(x) // this used to evaluate x
f: (x: => Int)Int
scala> f { println("hi") ; 42 }
res8: Int = 8
An exception was made to "preserve the by-name behavior" of the incoming x.
This mattered to people because of eta expansion:
scala> def k(y: => Int)(z: Int) = y + y + z
k: (y: => Int)(z: Int)Int
scala> def f(x: => Int) = k(x)(_) // normally, evaluate what you can now
f: (x: => Int)Int => Int
scala> val g = f { println("hi") ; 42 }
g: Int => Int = <function1>
scala> g(6)
hi
hi
res11: Int = 90
The question is how many greetings do you expect?
More quirks:
scala> def f(x: => Int) = (1 to 5) foreach (_ => x)
f: (x: => Int)Unit
scala> def g(x: () => Int) = (1 to 5) foreach (_ => x())
g: (x: () => Int)Unit
scala> var y = 0
y: Int = 0
scala> y = 0 ; f { y += 1 ; println("hi") ; y }
hi
hi
hi
hi
hi
y: Int = 5
scala> y = 0 ; g { y += 1 ; println("hi") ; () => y }
hi
y: Int = 1
scala> y = 0 ; g { () => y += 1 ; println("hi") ; y }
hi
hi
hi
hi
hi
y: Int = 5
Functions don't cause this problem:
scala> object X { def f(i: Int) = i ; def f(i: => Int) = i+1 }
defined object X
scala> X.f(0)
res12: Int = 0
scala> trait Y { def f(i: Int) = i }
defined trait Y
scala> object X extends Y { def f(i: => Int) = i+1 }
defined object X
scala> X.f(0)
<console>:11: error: ambiguous reference to overloaded definition,
both method f in object X of type (i: => Int)Int
and method f in trait Y of type (i: Int)Int
match argument types (Int)
X.f(0)
^
Compare method types:
http://www.scala-lang.org/files/archive/spec/2.11/03-types.html#method-types
This is not a pedantic distinction; irrespective of the current implementation, it can be confusing to think of a by-name parameter as "really" a function.
Another way of saying what has already been said is that inside f you invoke the function x three times. The first time it increments the y var and returns 1. The second time it again increments y returning 2 and the third time it again increments y and returns 3.
If you want it invoked only once then you may want to do something like this:
def f(x: => Int) : Int = x * x * x
var y = 0
lazy val xx = {
y += 1
println("invoked")
y
}
f {xx}
This will print 'invoked' only once and result in a returned value of 1.
x: T means need a T value.
x: => T means need a T value, but it is call by name.
x: () => T This means need a function given nothing to T
However, this question is not related to the difference between function and method.
The reason is call by name is invoked every time you try to use it.
change to call by value def f(x: Int) : Int, it will only invoke once.
Because you increment y by 1 every time the argument is used inside f
The result which your function f() returns is changing, because there is a global variable that is incremented with every subsequent call to that function.
the x in f(x: => Int) is interpreted as "some function that returns Int". So it has to be called 3 times to evaluate the x*x*x expression. With every call, you increment the global variable and return the result, which is how you arrive at three subsequent natural numbers (because the global variable is initialized to 0). Hence 1*2*3.

Explain some code which uses recursion and currying

How is the method product used in this code ?
The result for this function is 3600
So product takes a function : f ,
f takes an Int parameter which returns an Int parameter.
But does (a: Int, b: Int) not indicate that a function which takes two Int parameters are returned ?
I'm confused as to what is is occuring in this line :
f(a) * product(f)(a + 1, b)
Complete function :
def product(f: Int => Int)(a: Int, b: Int): Int =
if(a > b) 1
else {
f(a) * product(f)(a + 1, b)
}
product(x => x * x)(3 , 5)
In Scala, methods can have multiple parameter lists. In this example, the method product has two parameter lists: (f: Int => Int) and (a: Int, b: Int).
The first parameter list contains one parameter named f, which is of type Int => Int (a function that takes an Int and returns an Int).
The second parameter list contains two parameters named a and b which are both of type Int.
The expressions product(f)(a + 1, b) and product(x => x * x)(3 , 5) simply call the method with all three parameters.
The advantage of this is that you can "call" product with only the first parameter list. What you'll then get is a function that you can call by supplying the second parameter list. For example:
val fn = product(x => x * x) // only the first parameter list is applied
fn(3, 5) // fn is a function which you can pass the second list
"Calling" product with only the first parameter list is called currying.