I don't have very clear the partial application of functions in Scala...
I will do an example:
def myOperation(x: Int)(y: Int): Int = {
val complexVal = complexCalc(x)
println("complexVal calculated")
complexVal + y
}
def complexCalc(x: Int): Int = x * 2
val partial = myOperation(5)_
println("calculate")
println("result(3): " + partial(3))
println("result(1): " + partial(1))
The output of this will be:
calculate
complexVal calculated
result(3): 13
complexVal calculated
result(1): 11
So the complexVal was calculated 2 times, what if I want to calculate it just once?
For who has javascript knowledge something like:
function myOperation(x) {
var complexVal = complexCalc(x)
return function(y){
complexVal + y
}
}
EDIT:
So what's the difference between what I've written previously and this:
def myOperation2(x: Int, y: Int): Int = {
val complexVal = complexCalculation(x)
println("complexVal calculated")
complexVal + y
}
val partial = myOperation(5)_
val partial2 = myOperation2(5, _: Int)
You can explicitly return a function from myOperation:
def myOperation(x: Int): Int => Int = {
val complexVal = complexCalc(x)
println("complexVal calculated")
(y: Int) => complexVal + y
}
Partial application just creates a new function by filling in some of the arguments of an existing function, but does not actually execute any part of that function.
For what you're trying to do, you want to return a function from a function. In this case, what you're actually doing is currying (true currying).
Try this:
def myOperation(x : Int) : (Int => Int => Int) = {
val complexVal = complexCalc(x)
(y : Int) => complexVal + y
}
Partial application binds a value to a function argument to give you a function with decreased arity (i.e. fewer arguments). This does not provide any form of memoisation of your expensive computation.
Lee's answer is perfectly good way of solving that problem.
Related
This sum function working fine, but I am having trouble to write the version that swap x and f:(Int=>Int)
Works fine:
def sum(f:Int=>Int):Int=>Int = {
def ret_fun(x:Int):Int =
if (x==1) f(1)
else f(x)+ret_fun(x-1)
ret_fun
}
Did not work:
def sum(x:Int):Int=>Int = {
def ret_fun(f:Int=>Int):Int =
if (x==1) f(1)
else f(x)+ret_fun(x-1)
ret_fun
}
Did anyone know how to solve this?
First of all, the return type of the second sum should be (Int => Int) => Int, because it's supposed to return a function that accepts an Int => Int function, not an Int number.
Unfortunately you can't iterate over x using recursion of ret_fun, because x is not its argument. However you could use an indirect recursion of sum
def sum(x: Int): (Int => Int) => Int = {
def ret_fun(f: Int => Int): Int =
if (x == 1) f(1)
else f(x) + sum(x - 1)(f)
ret_fun
}
I imagine it may defeat the purpose of your exercise, because it's essentially the same as saying:
def sum(x: Int)(f: Int => Int): Int =
if (x == 1) f(1)
else f(x) + sum(x - 1)(f)
If your idea was to implement ret_fun using direct recursion and achieve the full analogy with the first example, let me comment on why it's problematic.
The reason is that the stop condition x == 1 is defined in terms of x and not in terms of f(x), so it's hard to determine which invocation should recurse and which shouldn't without changing the logic of the algorithm
def sum(x: Int): (Int => Int) => Int = {
def ret_fun(f: Int => Int): Int =
if (???) f(1)
else f(x) + ret_fun(x => f(x - 1))
ret_fun
}
We can, for instance, try if (f(x) == 0) 0, but as I said it will pretty much break the algorithm and will calculate f(x) + f(x - 1) + ... + 0 instead of f(x) + f(x - 1) + ... + f(1)
If you are fine with your second function depending on the first one, you just define it as this:
def sum(x: Int): (Int=>Int) => Int = f => sum(f)(x)
Otherwise you can do this:
def sum(x: Int): (Int => Int) => Int = f => f(x) + (if (x == 1) 0 else sum(x - 1)(f))
There's no need to define ret_fun separately.
If you absolutely want ret_fun, though, you can add x as a parameter to ret_fun, like this:
def sum(x: Int): (Int => Int) => Int = {
def ret_fun(x: Int)(f: Int => Int): Int =
if (x == 1) f(1)
else f(x) + ret_fun(x - 1)(f)
ret_fun(x)
}
If you want the function to be the first parameter, then you can do this, which is basically the same:
def sum(x: Int): (Int => Int) => Int = {
def ret_fun(f: Int => Int)(x: Int): Int =
if (x == 1) f(1)
else f(x) + ret_fun(f)(x - 1)
ret_fun(_)(x)
}
I'm trying to understand how to leverage monads in scala to solve simple problems as way of building up my familiarity. One simple problem is estimating PI using a functional random number generator. I'm including the code below for a simple stream based approach.
I'm looking for help in translating this to a monadic approach. For example, is there an idiomatic way convert this code to using the state (and other monads) in a stack safe way?
trait RNG {
def nextInt: (Int, RNG)
def nextDouble: (Double, RNG)
}
case class Point(x: Double, y: Double) {
val isInCircle = (x * x + y * y) < 1.0
}
object RNG {
def nonNegativeInt(rng: RNG): (Int, RNG) = {
val (ni, rng2) = rng.nextInt
if (ni > 0) (ni, rng2)
else if (ni == Int.MinValue) (0, rng2)
else (ni + Int.MaxValue, rng2)
}
def double(rng: RNG): (Double, RNG) = {
val (ni, rng2) = nonNegativeInt(rng)
(ni.toDouble / Int.MaxValue, rng2)
}
case class Simple(seed: Long) extends RNG {
def nextInt: (Int, RNG) = {
val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL
val nextRNG = Simple(newSeed)
val n = (newSeed >>> 16).toInt
(n, nextRNG)
}
def nextDouble: (Double, RNG) = {
val (n, nextRNG) = nextInt
double(nextRNG)
}
}
}
object PI {
import RNG._
def doubleStream(rng: Simple):Stream[Double] = rng.nextDouble match {
case (d:Double, next:Simple) => d #:: doubleStream(next)
}
def estimate(rng: Simple, iter: Int): Double = {
val doubles = doubleStream(rng).take(iter)
val inside = (doubles zip doubles.drop(3))
.map { case (a, b) => Point(a, b) }
.filter(p => p.isInCircle)
.size * 1.0
(inside / iter) * 4.0
}
}
// > PI.estimate(RNG.Simple(10), 100000)
// res1: Double = 3.14944
I suspect I'm looking for something like replicateM from the Applicative monad in cats but I'm not sure how to line up the types or how to do it in a way that doesn't accumulate intermediate results in memory. Or, is there a way to do it with a for comprehension that can iteratively build up Points?
Id you want to iterate using monad in a stack safe way, then there is a tailRecM method implemented in Monad type class:
// assuming random generated [-1.0,1.0]
def calculatePi[F[_]](iterations: Int)
(random: => F[Double])
(implicit F: Monad[F]): F[Double] = {
case class Iterations(total: Int, inCircle: Int)
def step(data: Iterations): F[Either[Iterations, Double]] = for {
x <- random
y <- random
isInCircle = (x * x + y * y) < 1.0
newTotal = data.total + 1
newInCircle = data.inCircle + (if (isInCircle) 1 else 0)
} yield {
if (newTotal >= iterations) Right(newInCircle.toDouble / newTotal.toDouble * 4.0)
else Left(Iterations(newTotal, newInCircle))
}
// iterates until Right value is returned
F.tailRecM(Iterations(0, 0))(step)
}
calculatePi(10000)(Future { Random.nextDouble }).onComplete(println)
It uses by-name param because you could try to pass there something like Future (even though the Future is not lawful), which are eager, so you would end up with evaluating the same thing time and time again. With by name param at least you have the chance of passing there a recipe for side-effecting random. Of course, if we use Option, List as a monad holding our "random" number, we should also expect funny results.
The correct solution would be using something that ensures that this F[A] is lazily evaluated, and any side effect inside is evaluated each time you need a value from inside. For that you basically have to use some of Effects type classes, like e.g. Sync from Cats Effects.
def calculatePi[F[_]](iterations: Int)
(random: F[Double])
(implicit F: Sync[F]): F[Double] = {
...
}
calculatePi(10000)(Coeval( Random.nextDouble )).value
calculatePi(10000)(Task( Random.nextDouble )).runAsync
Alternatively, if you don't care about purity that much, you could pass side effecting function or object instead of F[Int] for generating random numbers.
// simplified, hardcoded F=Coeval
def calculatePi(iterations: Int)
(random: () => Double): Double = {
case class Iterations(total: Int, inCircle: Int)
def step(data: Iterations) = Coeval {
val x = random()
val y = random()
val isInCircle = (x * x + y * y) < 1.0
val newTotal = data.total + 1
val newInCircle = data.inCircle + (if (isInCircle) 1 else 0)
if (newTotal >= iterations) Right(newInCircle.toDouble / newTotal.toDouble * 4.0)
else Left(Iterations(newTotal, newInCircle))
}
Monad[Coeval].tailRecM(Iterations(0, 0))(step).value
}
Here is another approach that my friend Charles Miller came up with. It's a bit more direct since it uses RNG directly but it follows the same approach provided by #Mateusz Kubuszok above that leverages Monad.
The key difference is that it leverages the State monad so we can thread the RNG state through the computation and generate the random numbers using the "pure" random number generator.
import cats._
import cats.data._
import cats.implicits._
object PICharles {
type RNG[A] = State[Long, A]
object RNG {
def nextLong: RNG[Long] =
State.modify[Long](
seed ⇒ (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL
) >> State.get
def nextInt: RNG[Int] = nextLong.map(l ⇒ (l >>> 16).toInt)
def nextNatural: RNG[Int] = nextInt.map { i ⇒
if (i > 0) i
else if (i == Int.MinValue) 0
else i + Int.MaxValue
}
def nextDouble: RNG[Double] = nextNatural.map(_.toDouble / Int.MaxValue)
def runRng[A](seed: Long)(rng: RNG[A]): A = rng.runA(seed).value
def unsafeRunRng[A]: RNG[A] ⇒ A = runRng(System.currentTimeMillis)
}
object PI {
case class Step(count: Int, inCircle: Int)
def calculatePi(iterations: Int): RNG[Double] = {
def step(s: Step): RNG[Either[Step, Double]] =
for {
x ← RNG.nextDouble
y ← RNG.nextDouble
isInCircle = (x * x + y * y) < 1.0
newInCircle = s.inCircle + (if (isInCircle) 1 else 0)
} yield {
if (s.count >= iterations)
Right(s.inCircle.toDouble / s.count.toDouble * 4.0)
else
Left(Step(s.count + 1, newInCircle))
}
Monad[RNG].tailRecM(Step(0, 0))(step(_))
}
def unsafeCalculatePi(iterations: Int) =
RNG.unsafeRunRng(calculatePi(iterations))
}
}
Thanks Charles & Mateusz for your help!
I have implemented a Calculation class that takes 2 parameters: a calculation input that is a call-by-name param and also a cost. When I try to flatMap calculations, the first part of it gets executed. Is it possible to defer everything in flatMap and still provide the total cost?
class Calculation[+R](input: => R, val cost: Int = 0) {
def value: R = input
def map[A](f: R => A): Calculation[A] =
new Calculation(f(input), cost)
def flatMap[A](f: R => Calculation[A]): Calculation[A] = {
val step = f(input)
new Calculation(step.value, cost + step.cost)
}
}
object Rextester extends App {
val f1 = new Calculation({
println("F1")
"F1"
})
val f2 = f1.flatMap(s => new Calculation({
println("F2")
s + " => F2"
}))
println(f2.cost)
}
Once f2 is declared (flatMap is called), we can see that "F1" will be printed. The printed cost is "15", which is correct, but I would like to have the actual calculation fully deferred, meaning that I shouldn't see the f1 being executed when I calculate the cost.
You just need a little more laziness, so that the cost isn't eagerly evaluated in the flatMap:
class Calculation[+R](input: => R, c: => Int = 0) {
def value: R = input
lazy val cost: Int = c
def map[A](f: R => A): Calculation[A] =
new Calculation(f(input), cost)
def flatMap[A](f: R => Calculation[A]): Calculation[A] = {
lazy val step = f(value)
new Calculation(step.value, cost + step.cost)
}
}
Note that this still might not have exactly the semantics you want (e.g. calling f2.value twice in a row will results in both F1 and F2 being printed the first time, and only F2 the second), but it does keep the side effect from occurring when f2 is defined.
If I understand your requirement
defer everything in flatMap and still provide the total cost
correctly, then you want to compute an estimate for the total costs before making any computations. I don't see how this is supposed to work with the signature flatMap[A](f: R => Calculation[A]): Calculation[A] - your cost is attached to Calculation[A], and your Calculation[A] depends on a concrete instance of R, so you cannot compute the cost before computing R.
Constant costs for computation steps
Here is a completely different proposal:
sealed trait Step[-A, +B] extends (A => B) { outer =>
def estimatedCosts: Int
def andThen[U >: B, C](next: Step[U, C]): Step[A, C] = new Step[A, C] {
def apply(a: A): C = next(outer(a))
def estimatedCosts = outer.estimatedCosts + next.estimatedCosts
}
def result(implicit u_is_a: Unit <:< A): B = this(u_is_a(()))
}
type Computation[+R] = Step[Unit, R]
The trait Step represents a computation step, for which the costs do not depend on the input. It's essentially just a Function[A, B] with an integer value attached to it. Your Computation[R] then becomes a special case, namely Step[Unit, R].
Here is how you can use it:
val x = new Step[Unit, Int] {
def apply(_u: Unit) = 42
def estimatedCosts = 0
}
val mul = new Step[Int, Int] {
def apply(i: Int) = {
println("<computing> adding is easy")
i + 58
}
def estimatedCosts = 10
}
val sqrt = new Step[Int, Double] {
def apply(i: Int) = {
println("<computing> finding square roots is difficult")
math.sqrt(i)
}
def estimatedCosts = 50
}
val c: Computation[Double] = x andThen mul andThen sqrt
println("Estimated costs: " + c.estimatedCosts)
println("(nothing computed so far)")
println(c.result)
If you run it, you obtain:
Estimated costs: 60
(nothing computed so far)
<computing> adding is easy
<computing> finding square roots is difficult
10.0
What it does is the following:
It starts with value 42, adds 58 to it, and then computes the square root of the sum
Addition is set to cost 10 units, square root costs 50.
It gives you the cost estimate of 60 units, without performing any computations.
Only when you invoke .result does it compute the actual result 10.0
Admittedly, it's not very useful for anything except very coarse order-of-magnitude estimates. It's so coarse that even using Ints barely makes any sense.
Non-constant costs per step
You can make your cost estimates more accurate by keeping track of a size estimate as follows:
trait Step[-A, +B] extends (A => B) {
def outputSizeEstimate(inputSizeEstimate: Int): Int
def costs(inputSizeEstimate: Int): Int
}
trait Computation[+R] { outer =>
def result: R
def resultSize: Int
def estimatedCosts: Int
def map[S](step: Step[R, S]): Computation[S] = new Computation[S] {
def result: S = step(outer.result)
def estimatedCosts: Int = outer.estimatedCosts + step.costs(outer.resultSize)
def resultSize: Int = step.outputSizeEstimate(outer.resultSize)
}
}
val x = new Computation[List[Int]] {
def result = (0 to 10).toList
def resultSize = 10
def estimatedCosts = 10
}
val incrementEach = new Step[List[Int], List[Int]] {
def outputSizeEstimate(inputSize: Int) = inputSize
def apply(xs: List[Int]) = {
println("incrementing...")
xs.map(1.+)
}
def costs(inputSize: Int) = 3 * inputSize
}
val timesSelf = new Step[List[Int], List[(Int, Int)]] {
def outputSizeEstimate(n: Int) = n * n
def apply(xs: List[Int]) = {
println("^2...")
for (x <- xs; y <- xs) yield (x, y)
}
def costs(n: Int) = 5 * n * n
}
val addPairs = new Step[List[(Int, Int)], List[Int]] {
def outputSizeEstimate(n: Int) = n
def apply(xs: List[(Int, Int)]) = {
println("adding...")
xs.map{ case (a, b) => a + b }
}
def costs(n: Int) = 7 * n
}
val y = x map incrementEach map timesSelf map addPairs
println("Estimated costs (manually): " + (10 + 30 + 500 + 700))
println("Estimated costs (automatically): " + y.estimatedCosts)
println("(nothing computed so far)")
println(y.result)
The output looks encouraging:
Estimated costs (manually): 1240
Estimated costs (automatically): 1240
(nothing computed so far)
incrementing...
^2...
adding...
List(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...[omitted]..., 20, 21, 22)
Note that the approach is not restricted to lists and integers: the size estimates can be arbitrarily complicated. For example, they could be dimensions of matrices or tensors. Actually, they don't have to be sizes at all. Those estimates could just as well contain any other kind of "static conservative estimates", like types or logical predicates.
Non-constant costs, using Writer
Using the Writer monad from Cats, we can express the same idea more succinctly by replacing the two methods outputSizeEstimate and costs on a Step by a single method that takes an Int and returns a Writer[Int, Int]:
Writers .value corresponds to size estimate for the output
Writers .written corresponds to costs of the step (which might depend on the input size)
Full code:
import cats.data.Writer
import cats.syntax.writer._
import cats.instances.int._
object EstimatingCosts extends App {
type Costs = Int
type Size = Int
trait Step[-A, +B] extends (A => B) {
def sizeWithCosts(inputSizeEstimate: Size): Writer[Costs, Size]
}
object Step {
def apply[A, B]
(sizeCosts: Size => (Size, Costs))
(mapResult: A => B)
: Step[A, B] = new Step[A, B] {
def apply(a: A) = mapResult(a)
def sizeWithCosts(s: Size) = { val (s2, c) = sizeCosts(s); Writer(c, s2) }
}
}
trait Computation[+R] { outer =>
def result: R
def sizeWithCosts: Writer[Costs, Size]
def size: Size = sizeWithCosts.value
def costs: Costs = sizeWithCosts.written
def map[S](step: Step[R, S]): Computation[S] = new Computation[S] {
lazy val result: S = step(outer.result)
lazy val sizeWithCosts = outer.sizeWithCosts.flatMap(step.sizeWithCosts)
}
}
object Computation {
def apply[A](initialSize: Size, initialCosts: Costs)(a: => A) = {
new Computation[A] {
lazy val result = a
lazy val sizeWithCosts = Writer(initialCosts, initialSize)
}
}
}
val x = Computation(10, 10){ (0 to 10).toList }
val incrementEach = Step(n => (n, 3 * n)){ (xs: List[Int]) =>
println("incrementing...")
xs.map(1.+)
}
val timesSelf = Step(n => (n * n, 5 * n * n)) { (xs: List[Int]) =>
println("^2...")
for (x <- xs; y <- xs) yield (x, y)
}
val addPairs = Step(n => (n, 7 * n)) { (xs: List[(Int, Int)]) =>
println("adding...")
xs.map{ case (a, b) => a + b }
}
val y = x map incrementEach map timesSelf map addPairs
println("Estimated costs (manually): " + (10 + 30 + 500 + 700))
println("Estimated costs (automatically): " + y.costs)
println("(nothing computed so far)")
println(y.result)
}
The output stays exactly the same as in the previous section.
PS: I think I came up with a more concise way to summarize this entire answer:
Use the product category of the ordinary ambient Scala category (types and functions) with the monoid of endomorphisms on object Int in the Kleisli category of Writer[Int, ?].
In some hypothetical language, the answer might have been:
Use Sc * End{Kl(Writer[Int, ?])}[Int].
First of all there is no reason to re-invent your own Functor and FlatMap and I would strongly advice you to use existing implementation.
If you need deffered computation than cats.Writer[Int, ?] is your friend.
With its support you can write your cost as well as get functor and monad instances.
Let me give you an example. We start with some initial cost
val w = Writer.put("F1")(0)
w.flatMap(v => Writer.value(v + "F2"))
I have a method fun. It takes a function literal as a parameter and return Int.
def fun(arg: (Int) => Int): Int = {
val ret = 5 * arg + 10
ret
}
It represent a function f(x) = 5x+10, which could take a parameter as another function (i.g. g(x) = x+1), so f(g(2)) = 5(2+1)+10 = 25
But my Scala code doesn't compile. Why?
Scala is a functional programming language, it has a very nice feature where we can pass functions as arguments, to store them in variables, and to return them from other functions.
object FunctionCalc{
def f(Input: Int => Int) : Int ={
val temp = 10
(Input(5) + temp ) // It takes functions as input which take input as Int and return Int.
}
def f(Input:Int) :Int ={
Input + 4 //overloaded function
}
def g(arg : Int) :Int= {
arg+1 //adding 1
}
def h(arg:Int) : Int ={
arg+3 //adding 3
}
def main(args: Array[String]) {
println( f(g(2)))
println(f(h(4)))
println(f(6))
}
}
Consider the above example we are passing functions g and h as inputs to f().
Because you are using function "arg:Int=>Int" as and argument in your code.
"arg" is a function you can use it like this.
def g(x:Int) = x+1
def f(arg:Int=>Int)(y:Int) = 5* arg(y) + 10
scala> f(g)(2)
res23: Int = 25
In the following code:
def product(f: Int => Int)(a:Int, b:Int): Int =
if (a > b) 1
else f(a) * product(f)(a + 1, b)
The parameters a and b are passed to the inner function, but you could write exactly the same function definition like so:
def product(f: Int => Int, a:Int, b:Int): Int =
if (a > b) 1
else f(a) * product(f, a + 1, b)
So what is the purpose of separating the parameters? In other words, why do this:
(f: Int => Int)(a:Int, b:Int)
when you can more clearly write:
(f: Int => Int, a:Int, b:Int)
Another feature of multiple parameters lists is partial application:
def sum3(a: Int)(b: Int)(c: Int): Int = a + b + c
val g: Int => Int => Int = sum3(10) _
val h: Int => Int = g(20)
val r: Int = h(30) // 10 + 20 + 30 = 60
You can partially apply a function and obtain another function which is equivalent to the original one but with one of the arguments fixed. _ after sum3(10) is needed because sum3 is a method, not a function, and _ converts methods to functions.
This is very useful when you are using higher-order functions:
def adder(x: Int)(y: Int) = x + y
Seq(1, 2, 3, 4) map adder(10) // Seq(11, 12, 13, 14)
When partially applied method/function is used as an argument of a higher-order call, _ is not needed, and the syntax becomes very succinct.
Another use case of this feature is that if you want to create a control structure that looks like it's built into Scala programming language itself.
For example, I could write an control structure named times which help me execute the code block exactly n times by the following method definition:
// since block is call by name, it will not be evaluate when you call it.
def times(n: Int)(block: => Any): Unit = {
for (i <- 0 until n) {
block // evaluate(execute) block
}
}
// Now I can use the times method like a control structure
times(5) {
println("Hello World");
}
It depends whether there is implicit parameter (which can't be properly mixed with plain ones)...
def foo(i: Int)(implicit p: P): Foo
... and the way you want to call it ...
def foo1(a: Int)(b: Int => Boolean): Boolean
foo1(9) { i => false }
def foo2(a: Int, b: Int => Boolean): Boolean
foo2(9, { i => false })