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)))
Related
I'm a beginner learning scala and looking into anon functions and vals.
I'm not able to convert {case e if e % 2 == 0 => e} to a Val. I've tried different syntax (sample shown below) to no avail. There is no real purpose for converting to val; just trying to get a deeper understanding.
package exercises.functions
object CollectVal extends App {
println(List(1,2,3,4,5).collect{case e if e % 2 == 0 => e})
// val onlyEvens: Int = e:Int => Int = e if (e % 2 == 0 ) => e
// val onlyEvens = e:Int = {case e if e % 2 == 0 => e}
println(List(1,2,3,4,5).collect{onlyEvens})
}
Any help is appreciated
Thanks!
What you need to express is a function. So the type of the variable in this case is:
val onlyEvens: Int => Int
In particular, collect accept a PartialFunction (i.e. a function that is not defined for some input value). So it is more correct to write:
val onlyEvens: PartialFunction[Int, Int] = { case e if e % 2 == 0 => e }
Finally, you can pass this val in the collect method:
List(1,2,3,4,5).collect(onlyEvens)
Scastie
Syntax to assign an anonymous function to a val would be something like this (note parentheses around e):
val x: Int => Int = (e) => if (e % 2 == 0) e else ???
or equivalently, but a bit shorter: val x = (e: Int) => if (e % 2 == 0) e else ???
But it looks like what you are looking for is a partial function rather than just a function. PartialFunction is like a regular function, but it is only defined for some of the possible values of its parameter. In your case, you want it only defined for even numbers:
val x = PartialFunction[Int, Int] { case e if e % 2 == 0 => e }
The { case foo => bar } shorthand works for partial functions but not regular functions, that's why you were having problems trying to define a function that way. This creates a PartialFunction that is defined for all integer values that match one of the case clauses, and not for any others.
I want to write a function which will return true if given an even number as an argument or false otherwise. additionally, write a function that will filter a list of numbers returning just the even numbers. All done using Scala functional programming. This is what I have:
def isEven(n:Int): Boolean = n % 2 == 0
println(isEven(4))
val filterEven = ( xs :List[Int] ) => {
for( x <- xs; if x % 2 == 0 ) yield x
}
println(filterEven(List(3,2,4,5,6,22,91)))
My question is, how can I pass the first function "isEven" to to the "filterEven" function in order to replace the "if-statement"?
Regards.
You can pass isEven as a parameter to xs.filter
def filterEven(xs: List[Int]) = xs.filter(isEven)
This is functionally equivalent to:
def filterEven(xs: List[Int]) = for { x <- xs if isEven(x) } yield x
First you give it a name when it is passed in.
val filterEven = (xs :List[Int], filterFunc: Int => Boolean) => {
Then you invoke it under its new name.
for(x <- xs; if filterFunc(x)) yield x
Note that now filterEven is not a good name for your function. The parameter passed in as filterFunc will determine whether you filter even, or odd, or less than 100, or .....
So I have a generic compose combinator.
Recall that the composition of two functions—f and g-- is h(x) = f(g(x))
def inc(x: Double) = x + 1
def double(x: Double) = 2 * x
def compose[A,B,C](f: B => C, g: A => B, x: A): C = f(g(x))
//TEST
println(compose(double, inc, 2.0))
//OUTPUT
// 6.0
But now I want to implement the self-composition iterator combinator, recursively, using my compose function where:
def selfIter[T](f: T=>T, n: Int) = f composed with itself n times.
I tried doing this:
def selfIter[T](f: T, n: Int): T = {
if(n == 0) f
else f + selfIter(f, n-1)
}
//TEST
println(selfIter(compose(double, inc, 2.0), 2))
I get an error, I know I'm doing something fundamentally wrong, but I cant figure out what I need to do.
In this case, the output should be 14.0 because first call will be 2(2+1) = 6.0, and then second call will be 2(6.0 + 1) = 14.0
Question: How should I refactor my code so that selfIter will compose f with itself n times until we have n == 0, and returns the final value
The easiest way to solve this kind of problems is to use the combinators provided by Scala. Also you should first compose the function you want to use and then apply the input
def compose[A,B,C](f: B => C, g: A => B): A => C = g.andThen(f)
def selfIter[T](f: T=>T, n: Int): T => T = Function.chain(List.fill(n)(f))
println(selfIter(compose(double, inc), 2)(2.0))
If compose signature could not be changed then
def compose[A,B,C](f: B => C, g: A => B, x: A): C = f(g(x))
def selfIter[T](f: T=>T, n: Int): T => T = Function.chain(List.fill(n)(f))
println(selfIter[Double](compose(double, inc, _), 2)(2.0))
But it makes much more sense the first solution
There are a few things going wrong here.
This f + selfIter(f, n-1) says that f (type T) must have a + method that takes another T as an argument. But you don't want to add these things, you want to compose them.
Here's a simpler way to get the result you're after.
Stream.iterate(2.0)(compose(double, inc, _))(2) // res0: Double = 14.0
If you're intent on a recursive method, this appears to achieve your goal.
def selfIter[T](start:T, n:Int)(f:T=>T): T = {
if (n < 2) f(start)
else f(selfIter(start, n-1)(f))
}
selfIter(2.0, 2)(compose(double, inc, _)) // res0: Double = 14.0
Whilst I understand what a partially applied/curried function is, I still don't fully understand why I would use such a function vs simply overloading a function. I.e. given:
def add(a: Int, b: Int): Int = a + b
val addV = (a: Int, b: Int) => a + b
What is the practical difference between
def addOne(b: Int): Int = add(1, b)
and
def addOnePA = add(1, _:Int)
// or currying
val addOneC = addV.curried(1)
Please note I am NOT asking about currying vs partially applied functions as this has been asked before and I have read the answers. I am asking about currying/partially applied functions VS overloaded functions
The difference in your example is that overloaded function will have hardcoded value 1 for the first argument to add, i.e. set at compile time, while partially applied or curried functions are meant to capture their arguments dynamically, i.e. at run time. Otherwise, in your particular example, because you are hardcoding 1 in both cases it's pretty much the same thing.
You would use partially applied/curried function when you pass it through different contexts, and it captures/fills-in arguments dynamically until it's completely ready to be evaluated. In FP this is important because many times you don't pass values, but rather pass functions around. It allows for higher composability and code reusability.
There's a couple reasons why you might prefer partially applied functions. The most obvious and perhaps superficial one is that you don't have to write out intermediate functions such as addOnePA.
List(1, 2, 3, 4) map (_ + 3) // List(4, 5, 6, 7)
is nicer than
def add3(x: Int): Int = x + 3
List(1, 2, 3, 4) map add3
Even the anonymous function approach (that the underscore ends up expanding out to by the compiler) feels a tiny bit clunky in comparison.
List(1, 2, 3, 4) map (x => x + 3)
Less superficially, partial application comes in handy when you're truly passing around functions as first-class values.
val fs = List[(Int, Int) => Int](_ + _, _ * _, _ / _)
val on3 = fs map (f => f(_, 3)) // partial application
val allTogether = on3.foldLeft{identity[Int] _}{_ compose _}
allTogether(6) // (6 / 3) * 3 + 3 = 9
Imagine if I hadn't told you what the functions in fs were. The trick of coming up with named function equivalents instead of partial application becomes harder to use.
As for currying, currying functions often lets you naturally express transformations of functions that produce other functions (rather than a higher order function that simply produces a non-function value at the end) which might otherwise be less clear.
For example,
def integrate(f: Double => Double, delta: Double = 0.01)(x: Double): Double = {
val domain = Range.Double(0.0, x, delta)
domain.foldLeft(0.0){case (acc, a) => delta * f(a) + acc
}
can be thought of and used in the way that you actually learned integration in calculus, namely as a transformation of a function that produces another function.
def square(x: Double): Double = x * x
// Ignoring issues of numerical stability for the moment...
// The underscore is really just a wart that Scala requires to bind it to a val
val cubic = integrate(square) _
val quartic = integrate(cubic) _
val quintic = integrate(quartic) _
// Not *utterly* horrible for a two line numerical integration function
cubic(1) // 0.32835000000000014
quartic(1) // 0.0800415
quintic(1) // 0.015449626499999999
Currying also alleviates a few of the problems around fixed function arity.
implicit class LiftedApply[A, B](fOpt: Option[A => B]){
def ap(xOpt: Option[A]): Option[B] = for {
f <- fOpt
x <- xOpt
} yield f(x)
}
def not(x: Boolean): Boolean = !x
def and(x: Boolean)(y: Boolean): Boolean = x && y
def and3(x: Boolean)(y: Boolean)(z: Boolean): Boolean = x && y && z
Some(not _) ap Some(false) // true
Some(and _) ap Some(true) ap Some(true) // true
Some(and3 _) ap Some(true) ap Some(true) ap Some(true) // true
By having curried functions, we've been able to "lift" a function to work on Option for as many arguments as we need. If our logic functions had not been curried, then we would have had to have separate functions to lift A => B to Option[A] => Option[B], (A, B) => C to (Option[A], Option[B]) => Option[C], (A, B, C) => D to (Option[A], Option[B], Option[C]) => Option[D] and so on for all the arities we cared about.
Currying also has some other miscellaneous benefits when it comes to type inference and is required if you have both implicit and non-implicit arguments for a method.
Finally, the answers to this question list out some more times you might want currying.
I have List[Int] in Scala. The List is List(1,2,3,4,5,6,7,8,9,10). I want to filter the list so that it only has even numbers. And I want to multiply the numbers with 2.
Is it possible?
As I state in my comment, collect should do what you want:
list.collect{
case x if x % 2 == 0 => x*2
}
The collect method allows you to both specify a criteria on the matching elements (filter) and modify the values that match (map)
And as #TravisBrown suggested, you can use flatMap as well, especially in situations where the condition is more complex and not suitable as a guard condition. Something like this for your example:
list.flatMap{
case x if x % 2 == 0 => Some(x*2)
case x => None
}
A for comprehension (which internally unfolds into a combination of map and withFilter) as follows,
for (x <- xs if x % 2 == 0) yield x*2
Namely
xs.withFilter(x => x % 2 == 0).map(x => x*2)
As #cmbaxter said, collect suits your need perfectly. The other nice thing about collect is that it figures out resulting type in case you're filtering by class:
scala> trait X
// defined trait X
scala> class Foo extends X
// defined class Foo
scala> class Bar extends X
// defined class Bar
scala> val xs = List(new Foo, new Bar, new Foo, new Bar)
// xs: List[X] = List(Foo#4cfa8227, Bar#78226c36, Foo#3f685162, Bar#11f406f8)
scala> xs.collect { case x: Foo => x }
// res1: List[Foo] = List(Foo#4cfa8227, Foo#3f685162)
On par, filter can't be that smart (see List[Foo] vs List[X]):
scala> xs.filter { case x: Foo => true; case _ => false }
// res3: List[X] = List(Foo#4cfa8227, Foo#3f685162)
This should do the work for you:
Filter first when the condition is p % 2 == 0 (for getting only even numbers).
And then use map to multiply those even numbers by 2.
var myList = List(1,2,3,4,5,6,7,8,9,10).filter(p => p % 2 == 0).map(p => {p*2})
I tend to like the filter approach.
val list1 = List(1,2,3,4,5,6,7,8,9,10)
list1.filter(x => x%2 == 0).map(_*2)
How about a good old fashioned fold?
xs.foldLeft(List[Y]()) { (ys, x) =>
val z = calculateSomethingOnX(x)
if (someConditionOnZ(z))
Y(x, z) :: ys
else
ys
}