Partially applied/curried function vs overloaded function - scala

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.

Related

Monad's left unit law does not seem to hold for Lists in scala. Are scala Lists not monads then?

Monads' "left unit law":
unit(x) flatMap f == f(x)
But:
(List(1) flatMap ((x: Int) => Some[Int](x))) == List(1) // true
((x: Int) => Some[Int](x))(1) == Some(1) // also true
So left unit law does not hold for lists in scala. Are lists not monads then?
First, the monad law assumes f: A => M[A] (here f: A => List[A]). This is not true of (x: Int) => Some[Int](x).
Second, List's flatMap is not monadic bind. It is more general than bind, because it takes an implicit CanBuildFrom that allows it to change its return type depending on what you want it to return. You can restrict it to bind like so
def bind[A](xs: List[A])(f: A => List[A]) = xs.flatMap(f) // implicit (List.canBuildFrom)
Now you can see that the law is satisfied:
bind(List(1))(x => List(x, x)) == List(1, 1)
I'm not a category theory or Haskell expert but I don't understand your question, and my response is too big for comment, not to mention code blocks look terrible in comment.
Haskell left identity law is return a >>= f ≡ f a, right?
In Scala:
return -> apply
>>= -> flatMap
So, left identity law for Scala List would be List(a).flatMap(f) = f(a)
In your case, val a = 1 and val f = (x: Int) => Some[Int](x). But this wouldn't even compile because Option is not a GenTraversableOnce; you can't return Option from a List.flatMap.
Instead, if we define val f = (x: Int) => List(x * 2), a double function
LHS: List(a).flatMap(f) = List(2)
RHS: f(a) = List(2)
LHS = RHS, left identity satisfied.
Am I missing something?

Function to compute partial derivatives of function with arbitrary many variables

I am trying to write a function in Scala that will compute the partial derivative of a function with arbitrary many variables. For example
One Variable(regular derivative):
def partialDerivative(f: Double => Double)(x: Double) = { (f(x+0.001)-f(x))/0.001 }
Two Variables:
def partialDerivative(c: Char, f: (Double, Double) => Double)(x: Double)(y: Double) = {
if (c == 'x') (f(x+0.0001, y)-f(x, y))/0.0001
else if (c == 'y') (f(x, y+0.0001)-f(x, y))/0.0001
}
I am wondering if there is a way to write partialDerivative where the number of variables in f do not need to be known in advance.
I read some blog posts about varargs but can't seem to come up with the correct signature.
Here is what I tried.
def func(f: (Double*) => Double)(n: Double*)
but this doesn't seem to be correct. Thanks for any help on this.
Double* means f accepts an arbitrary Seq of Doubles, which is not correct.
The only way I can think of to write something like this is using shapeless Sized. You will need more implicits than this, and possibly some type-level equality implicits as well; type-level programming in scala is quite complex and I don't have the time to debug this properly, but it should give you some idea:
def partialDerivative[N <: Nat, I <: Nat](f: Sized[Seq[Double], N] => Double)(i: I, xs: Sized[Seq[Double], N])(implicit diff: Diff[I, N]) = {
val (before, atAndAfter) = xs.splitAt(i)
val incrementedAtAndAfter = (atAndAfter.head + 0.0001) +: atAndAfter.tail
val incremented = before ++ incrementedAtAndAfter
(f(incremeted) - f(xs)) / 0.0001
}

Currying in Scala: multiple parameter lists vs returning a function

When using the following syntax to define functions with currying enabled:
def sum(x: Int)(y: Int)(z: Int) = x + y + z
one still has to suffix any calls to curried calls of sum with _:
sum _
sum(3) _
sum(3)(2) _
otherwise the compiler will complain.
So I resorted to:
val sum = (x: Int) => (y: Int) => (z: Int) => x + y + z
which works without the _.
Now the question: why does the multiple-parameter-lists version require _ in order for currying to kick in? Why aren't the semantics of those 2 versions equivalent in all contexts?
Also, is the latter version somehow discouraged? Does it suffer from any caveats?
The reason why those two semantics are different, is that methods and functions are not the same thing.
Methods are full-fledges JVM methods, whereas functions are values (i.e. instance of classes like Function1, Function2 and so on).
So
def sum(x: Int)(y: Int)(z: Int) = x + y + z
and
val sum = (x: Int) => (y: Int) => (z: Int) => x + y + z
may seem identical, but the first is an method, while the second is a Function1[Int, Function1[Int, Function1[Int, Int]]]
When you try to use a method where a function value is expected, the compiler automatically converts it to a function (a process called eta-expansion).
However, there are case in which the compiler doesn't eta-expand the methods automatically, such as the cases you exposed, in which you explicitly want to partially apply it.
Using _ triggers the eta-expansion, so a method is converted to a function, and everybody is happy.
According to the scala specification, you could also annotate the expected type, in which case the expansion is performed automatically:
def sum(x: Int)(y: Int)(z: Int) = x + y + z
val sumFunction: Int => Int => Int => Int = sum
which is the same reason why
def sum(x: Int, y: Int) = x + y
List(1,2,3).reduce(sum)
works, i.e. we're passing a method where a function is explicitly required.
Here's a more in-depth discussion of when scala performs an eta-expansion: https://stackoverflow.com/a/2394063/846273
Concerning the choice of which to adopt, I'll point you to this answer, which is very exhaustive.

Idiomatic Scala for applying functions in a chain if Option(s) are defined

Is there a pre-existing / Scala-idiomatic / better way of accomplishing this?
def sum(x: Int, y: Int) = x + y
var x = 10
x = applyOrBypass(target=x, optValueToApply=Some(22), sum)
x = applyOrBypass(target=x, optValueToApply=None, sum)
println(x) // will be 32
My applyOrBypass could be defined like this:
def applyOrBypass[A, B](target: A, optValueToApply: Option[B], func: (A, B) => A) = {
optValueToApply map { valueToApply =>
func(target, valueToApply)
} getOrElse {
target
}
}
Basically I want to apply operations depending on wether certain Option values are defined or not. If they are not, I should get the pre-existing value. Ideally I would like to chain these operations and not having to use a var.
My intuition tells me that folding or reducing would be involved, but I am not sure how it would work. Or maybe there is another approach with monadic-fors...
Any suggestions / hints appreciated!
Scala has a way to do this with for comprehensions (The syntax is similar to haskell's do notation if you are familiar with it):
(for( v <- optValueToApply )
yield func(target, v)).getOrElse(target)
Of course, this is more useful if you have several variables that you want to check the existence of:
(for( v1 <- optV1
; v2 <- optV2
; v3 <- optV3
) yield func(target, v1, v2, v3)).getOrElse(target)
If you are trying to accumulate a value over a list of options, then I would recommend a fold, so your optional sum would look like this:
val vs = List(Some(1), None, None, Some(2), Some(3))
(target /: vs) ( (x, v) => x + v.getOrElse(0) )
// => 6 + target
You can generalise this, under the condition that your operation func has some identity value, identity:
(target /: vs) ( (x, v) => func(x, v.getOrElse(identity)) )
Mathematically speaking this condition is that (func, identity) forms a Monoid. But that's by-the-by. The actual effect is that whenever a None is reached, applying func to it and x will always produce x, (None's are ignored, and Some values are unwrapped and applied as normal), which is what you want.
What I would do in a case like this is use partially applied functions and identity:
def applyOrBypass[A, B](optValueToApply: Option[B], func: B => A => A): A => A =
optValueToApply.map(func).getOrElse(identity)
You would apply it like this:
def sum(x: Int)(y: Int) = x + y
var x = 10
x = applyOrBypass(optValueToApply=Some(22), sum)(x)
x = applyOrBypass(optValueToApply=None, sum)(x)
println(x)
Yes, you can use fold. If you have multiple optional operands, there are some useful abstractions in the Scalaz library I believe.
var x = 10
x = Some(22).fold(x)(sum(_, x))
x = None .fold(x)(sum(_, x))
If you have multiple functions, it can be done with Scalaz.
There are several ways to do it, but here is one of the most concise.
First, add your imports:
import scalaz._, Scalaz._
Then, create your functions (this way isn't worth it if your functions are always the same, but if they are different, it makes sense)
val s = List(Some(22).map((i: Int) => (j: Int) => sum(i,j)),
None .map((i: Int) => (j: Int) => multiply(i,j)))
Finally, apply them all:
(s.flatten.foldMap(Endo(_)))(x)

Scala by Example - problems with currying

Not sure how to properly formulate the question, there is a problem with currying in the merge sort example from Scala by Example book on page 69. The function is defined as follows:
def msort[A](less: (A, A) => Boolean)(xs: List[A]): List[A] = {
def merge(xs1: List[A], xs2: List[A]): List[A] =
if (xs1.isEmpty) xs2
else if (xs2.isEmpty) xs1
else if (less(xs1.head, xs2.head)) xs1.head :: merge(xs1.tail, xs2)
else xs2.head :: merge(xs1, xs2.tail)
val n = xs.length/2
if (n == 0) xs
else merge(msort(less)(xs take n), msort(less)(xs drop n))
}
and then there is an example of how to create other functions from it by currying:
val intSort = msort((x : Int, y : Int) => x < y)
val reverseSort = msort((x:Int, y:Int) => x > y)
however these two lines give me errors about insufficient number of arguments. And if I do like this:
val intSort = msort((x : Int, y : Int) => x < y)(List(1, 2, 4))
val reverseSort = msort((x:Int, y:Int) => x > y)(List(4, 3, 2))
it WILL work. Why? Can someone explain? Looks like the book is really dated since it is not the first case of such an inconsistance in its examples. Could anyone point to something more real to read? (better a free e-book).
My compiler (2.9.1) agrees, there seems to be an error here, but the compiler does tell you what to do:
error: missing arguments for method msort in object $iw;
follow this method with `_' if you want to treat it as a partially applied function
So, this works:
val intSort = msort((x : Int, y : Int) => x < y) _
Since the type of intSort is inferred, the compiler doesn't otherwise seem to know whether you intended to partially apply, or whether you missed arguments.
The _ can be omitted when the compiler can infer from the expected type that a partially applied function is what is intended. So this works too:
val intSort: List[Int] => List[Int] = msort((x: Int, y: Int) => x < y)
That's obviously more verbose, but more often you will take advantage of this without any extra boilerplate, for example if msort((x: Int, y: Int) => x < y) were the argument to a function where the parameter type is already known to be List[Int] => List[Int].
Edit: Page 181 of the current edition of the Scala Language Specification mentions a tightening of rules for implicit conversions of partially applied methods to functions since Scala 2.0. There is an example of invalid code very similar to the one in Scala by Example, and it is described as "previously legal code".