Simple currying in scala - scala

I have the following two functions, written in scala:
def f: (Int,Int) => Int = (x,y) => x+y
def g: Int=>Int=>Int=x=>y=>x+y
Now I want to write a function that curries the function f, taking one argument, into a function g, taking two arguments.
Beside the definition I cant find a solution to this problem
curry: ((Int, Int) => Int) => (Int => Int => Int):
Any suggestions?

Can you simply use the curried function?
scala> def f: (Int,Int) => Int = (x,y) => x+y
f: (Int, Int) => Int
scala> val g = f.curried
g: Int => (Int => Int) = <function1>
scala> g(1)(2)
res0: Int = 3
Edit: an example of a curry function based on the source code of curried in Function2:
def curry[A,B,C](f: (A,B) => C): A => B => C = (x1: A) => (x2: B) => f(x1,x2)

scala> def f(x: Int, y: Int) = x + y
f: (x: Int, y: Int)Int
scala> def curry(fn: (Int, Int) => Int) = (x: Int) => (y: Int) => fn(x, y)
curry: (fn: (Int, Int) => Int)Int => (Int => Int)
scala> val g = curry(f)
g: Int => (Int => Int) = <function1>
scala> g(3)(4)
res0: Int = 7

Related

i'm new to scala. can somebody tell me why i'm getting a error illicit start of simple function when writing the def recur function

def fact(n: Int) = products(x => x)(1,n)
fact(5)
def mapReduce(f: Int => Int, combine: (Int, Int) => Int, zero: Int)(a:Int,b:Int): Int =
def recur(a: Int): Int =
if(a>b) zero
else combine(f(a),recur(a+1))
recur(a)
def sum(f: Int => Int) = mapReduce(f, (x, y) => x+y, 0)
def products(f: Int => Int) = mapReduce(f, (x, y) => x*y, 1)
sum(fact)(1,5)
products(fact)(1,5)
def mapReduce(f: Int => Int, combine: (Int, Int) => Int, zero: Int)(a:Int,b:Int): Int = {
def recur(a: Int): Int =
if (a > b) zero
else combine(f(a), recur(a + 1))
recur(a)
}
def sum(f: Int => Int): (Int, Int) => Int = mapReduce(f, (x, y) => x+y, 0)
def products(f: Int => Int): (Int, Int) => Int = mapReduce(f, (x, y) => x*y, 1)
def fact(n: Int) = products(x => x)(1,n)
fact(5)
sum(fact)(1,5)
products(fact)(1,5)
I tried it using scala 2.13 on a scala worksheet, here curly brackets are needed for mapReduce as it contains two expressions one is a function definition and another a function invocation. Secondly when methods that returns functions such as sum and products the return type need to be specified. But I wasn't able to reproduce the error that you mentioned.

why currying does not work with a function literal?

What is the logical reason that the first form works and not the second?
scala> val d = (a: Int, b: Int) => a + b
d: (Int, Int) => Int = <function2>
scala> val d = (a: Int)(b: Int) => a + b
<console>:1: error: not a legal formal parameter.
Note: Tuples cannot be directly destructured in method or function parameters.
Either create a single parameter accepting the Tuple1,
or consider a pattern matching anonymous function: `{ case (param1, param1) => ... }
val d=(a:Int)(b:Int)=>a+b
Because multiple parameter lists aren't allowed on function declarations. If you want to curry a function, you do:
scala> val d: Int => Int => Int = a => b => a + b
d: Int => (Int => Int) = $$Lambda$1106/512934838#6ef4cbe1
scala> val f = d(3)
f: Int => Int = $$Lambda$1109/1933965693#7e2c6702
scala> f(4)
res6: Int = 7
You can also create a single parameter list and partially apply it:
scala> val d = (a: Int, b: Int) => a + b
d: (Int, Int) => Int = $$Lambda$1064/586164630#7c8874ef
scala> d(4, _: Int)
res2: Int => Int = $$Lambda$1079/2135563436#4a1a412e
We partially applied d with 4, and we got back a function, Int => Int, which means when we supply the next argument, we'll get the result:
scala> res2(3)
res3: Int = 7
We can also create a named method, and use eta-expansion to create a curried function out of it:
scala> def add(i: Int)(j: Int): Int = i + j
add: (i: Int)(j: Int)Int
scala> val curriedAdd = add _
curriedAdd: Int => (Int => Int) = $$Lambda$1115/287609100#f849027
scala> val onlyOneArgumentLeft = curriedAdd(1)
onlyOneArgumentLeft: Int => Int = $$Lambda$1116/1700143613#77e9dca8
scala> onlyOneArgumentLeft(2)
res8: Int = 3
Function currying is possible.
val curryFunc = (a: Int) => (b: Int) => a + b
curryFunc now has the type Int => (Int => Int)

How to compose tupled unary functions by combining their input tuples

I've been playing around with shapeless for a bit now.
But, yesterday I got stuck when trying to compose tupled functions.
What I was looking into specifically is composing two unary functions f1: T => R and f2: R => U => S into f: TU => S where T is a TupleN and TU := (t1, ... , tn, u)
import shapeless.ops.tuple._
implicit class Composable[T <: Product, R](val f1: T => R) extends AnyVal{
def compose2[U, S](f2: R => U => S)(implicit p: Prepend[T, Tuple1[U]]): (p.Out => S) = {
// how to provide the two required implicits for Last[p.Out] and Init[p.Out]?
tu => f1.andThen(f2)(tu.init)(tu.last)
}
}
val f1: ((Int, Int)) => Int = x => x._1 * x._2
val f2: ((Int, Int, Int)) => Int = f1.compose2((y: Int) => (x3: Int) => x3 + y).apply _
What I've been struggling with is providing the implicit proof for the tuple operations last and init, so the above code won't compile!
From a logical perspective it feels trivial as result of Prepend, but I couldn't figure out a way. So any idea is welcome :)
Using shapeless's facilities to abstract over arity I got somehow closer:
import shapeless.ops.function.{FnFromProduct, FnToProduct}
import shapeless.{::, HList}
implicit class Composable[F](val f: F) extends AnyVal{
// the new param U is appended upfront
def compose2[I <: HList, R, U, S](f2: R => U => S)
(implicit ftp: FnToProduct.Aux[F, I => R], ffp: FnFromProduct[U :: I => S]): ffp.Out = {
ffp(list => f2.compose(ftp(f))(list.tail)(list.head))
}
}
val f1: (Int, Int) => Int = (x1,x2) => x1 * x2
val f2: (Int, Int, Int) => Int = f1.compose2((y: Int) => (x3: Int) => x3 + y).apply _
This works, but then again I was really looking for compose2 to work on unary tupled Function1s. Also, this results in f: (U, t1, ..., tn) => S rather than f: TU => S with TU := (t1, ... , tn, u).
As Miles says, this would be more convenient with an undo for Prepend, but since the length of the second part is fixed, an approach similar to the one in my other answer isn't too bad at all:
import shapeless.ops.tuple._
implicit class Composable[T <: Product, R](val f1: T => R) extends AnyVal {
def compose2[U, S, TU](f2: R => U => S)(implicit
p: Prepend.Aux[T, Tuple1[U], TU],
i: Init.Aux[TU, T],
l: Last.Aux[TU, U]
): (p.Out => S) =
tu => f1.andThen(f2)(i(tu))(l(tu))
}
And then:
scala> val f1: ((Int, Int)) => Int = x => x._1 * x._2
f1: ((Int, Int)) => Int = <function1>
scala> val f2: ((Int, Int, Int)) => Int =
| f1.compose2((y: Int) => (x3: Int) => x3 + y).apply _
f2: ((Int, Int, Int)) => Int = <function1>
scala> f2((2, 3, 4))
res1: Int = 10
The trick is adding the output of Prepend to the type parameter list for compose2—which will generally be inferred—and then using Prepend.Aux to make sure that it's inferred appropriately. You'll often find in Shapeless that you need to refer to the output type of a type class in other type class instances in the same implicit parameter list in this way, and the Aux type members make doing so a little more convenient.

Currying function from an existing answer is invalid

I tried running the below code:
val f: (a: Int) => (b: Int) => (c: Int) = a + b + c
found in this thread in the REPL and IntellijIDEA but it's apparently invalid.
From the REPL:
scala> val f: (a: Int) => (b: Int) => (c: Int) = a + b + c
<console>:1: error: ')' expected but ':' found.
val f: (a: Int) => (b: Int) => (c: Int) = a + b + c
^
Anyone knows why? My scala version is 2.10.1
Thank you
You write the type as if you were writing:
val a: 5 = 5
What you want is more like
val f = (a: Int) => (b: Int) => (c: Int) => a+b+c
To elaborate further the REPL will write
f: Int => (Int => (Int => Int)) = <function1>
Because function definition is right associative you could the type of f explicitly as follows
f: Int => Int => Int => Int = (a: Int) => (b: Int) => (c: Int) => a+b+c
If you explicitly give the function type like this the compiler does not need information about what a,b, and c are and you could simply write a => b => c => a+b+c instead.

How do I get (a, b) => c from a => b => c in Scala?

If I have:
val f : A => B => C
This is shorthand for:
val f : Function1[A, Function1[B, C]]
How do I get a function g with the signature:
val g : (A, B) => C = error("todo")
(i.e.)
val g : Function2[A, B, C] //or possibly
val g : Function1[(A, B), C]
in terms of f?
scala> val f : Int => Int => Int = a => b => a + b
f: (Int) => (Int) => Int = <function1>
scala> Function.uncurried(f)
res0: (Int, Int) => Int = <function2>
Extending retonym's answer, for completeness
val f : Int => Int => Int = a => b => a + b
val g: (Int, Int) => Int = Function.uncurried(f)
val h: ((Int, Int)) => Int = Function.tupled(g)
The converse functions for both of these operations are also provided on the Function object, so you could write the above backwards, if you wished
val h: ((Int, Int)) => Int = x =>(x._1 + x._2)
val g: (Int, Int) => Int = Function.untupled(h)
val f : Int => Int => Int = g.curried //Function.curried(g) would also work, but is deprecated. Wierd
Just to round out the answer, although there is a library method to do this, it may also be instructive to do it by hand:
scala> val f = (i: Int) => ((s: String) => i*s.length)
f: (Int) => (String) => Int = <function1>
scala> val g = (i: Int, s: String) => f(i)(s)
g: (Int, String) => Int = <function2>
Or in general,
def uncurry[A,B,C](f: A=>B=>C): (A,B)=>C = {
(a: A, b: B) => f(a)(b)
}
Similar to the answer by Rex Kerr but easier to read.
type A = String
type B = Int
type C = Boolean
val f: A => B => C = s => i => s.toInt+i > 10
val f1: (A, B) => C = f(_)(_)