Let
def f(i:Int)(j:Int) = i + j
and so
f(1) _
Int => Int = <function1>
However,
val f: (Int)(Int) => Int = (a:Int)(b:Int) => a + b // wrong
namely, error: ';' expected but '(' found. How to declare val f ?
Is this what you were looking for?
scala> val f: Int => Int => Int = a => b => a + b
f: Int => (Int => Int) = <function1>
scala> f(1)
res7: Int => Int = <function1>
scala> f(1)(2)
res8: Int = 3
Related
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)
So I have an expensive method with this signature
def func(param: Int): \/[String, Int]
I am trying to loop over a list of params and returns \/[String, List[Int]] but stop the loop whenever the method returns -\/.
I come up with this:
scala> def func(i: Int) = {
| if( i > 1 ) { println{"!!"} ;"error".left[Int]}
| else i.right[String]
| }
func: (i: Int)scalaz.\/[String,Int]
scala> val toList = (dis: scalaz.\/[String,Int]) => {dis.map(i => List(i))}
toList: scalaz.\/[String,Int] => scalaz.\/[String,List[Int]] = <function1>
scala> val composed = (func _) andThen toList
composed: Int => scalaz.\/[String,List[Int]] = <function1>
scala> (1 to 3).toList.foldLeftM(List[Int]().right[String]){(dis, i) =>
| for{
| a <- dis
| b <- composed(i)
| } yield a |+| b
| }
<console>:17: error: no type parameters for method foldLeftM: (f: (scalaz.\/[String,List[Int]], Int) => G[scalaz.\/[String,List[Int]]])(implicit M: scalaz.Monad[G])G[scalaz.\/[String,List[Int]]] exist so that it can be applied to arguments ((scalaz.\/[String,List[Int]], Int) => scalaz.\/[String,List[Int]])
--- because ---
argument expression's type is not compatible with formal parameter type;
found : (scalaz.\/[String,List[Int]], Int) => scalaz.\/[String,List[Int]]
required: (scalaz.\/[String,List[Int]], Int) => ?G[scalaz.\/[String,List[Int]]]
(1 to 2).toList.foldLeftM(List[Int]().right[String]){(dis, i) =>
^
<console>:17: error: type mismatch;
found : (scalaz.\/[String,List[Int]], Int) => scalaz.\/[String,List[Int]]
required: (scalaz.\/[String,List[Int]], Int) => G[scalaz.\/[String,List[Int]]]
(1 to 2).toList.foldLeftM(List[Int]().right[String]){(dis, i) =>
^
What's the G[_] here and what's the correct result type in foldLeftM ?
Solved by noted two mistake I made:
misunderstood about type of initial/carried over value, it should be List[Int] instead of \/
one has to explicit declare type parameter of foldLeftM
scala> def func(i: Int) = {
| if( i > 1 ) { println{"!!"} ;"error".left[Int]}
| else i.right[String]
| }
func: (i: Int)scalaz.\/[String,Int]
scala> val toList = (dis: scalaz.\/[String,Int]) => {dis.map(i => List(i))}
toList: scalaz.\/[String,Int] => scalaz.\/[String,List[Int]] = <function1>
scala> val composed = (func _) andThen toList
composed: Int => scalaz.\/[String,List[Int]] = <function1>
scala> val f = (dis: List[Int], i: Int) => composed(i).map(r => dis |+| r)
f: (List[Int], Int) => scalaz.\/[String,List[Int]] = <function2>
scala> (1 to 4).toList.foldLeftM[({type l[a] = String \/ a})#l, List[Int]](List[Int]())(f)
!!
res16: scalaz.\/[String,List[Int]] = -\/(error)
Im trying to write a function using currying to compute a Collatz series... But im getting lost when trying to write the parameters for construct6(...)
def c: Int => Int = construct6(isEven)(dec, inc)
//DONT KNOW WHAT TO DO HERE
def construct6: ((Int => Boolean) => (Int => Int, Int => Int)) => (i => (e, o)) = {
if (i(n)) e(n) else o(n)
}
def isEven: (Int) => (Boolean) = (a) => (a % 2 == 0)
def dec: (Int) => (Int) = (a) => (a / 2)
def inc: (Int) => (Int) = (a) => (a * 3 + 1)
You're construct6 function MUST take a Int n. Here is the function curried 3 times...
def construct6(i: Int => Boolean)(e: Int => Int, o: Int => Int)( n: Int): Int =
if (i(n)) e(n) else o(n)
When dealing with problems like this it is always important to look at the type signatures and see that they match up. Notice that construct6 MUST return an Int. We can doing some functional magic to make a function with a type signature to match Int => Int by doing this:
val c: Int => Int = construct6(isEven)(dec, inc)(_: Int)
We are partially applying the function you want for i, e, o, and leaving n as a variable.
Given:
def isEven: (Int) => (Boolean) = (a) => (a % 2 == 0)
def dec: (Int) => (Int) = (a) => (a / 2)
def inc: (Int) => (Int) = (a) => (a * 3 + 1)
you are still missing the n parameter to construct6 (as Andrew Cassidy says). Since you need to curry its parameters, it's more readable if you define construct6 like this (but it's basically the same definition you gave, I just added the n:Int at the end):
def construct6 (i:Int => Boolean)(e:(Int => Int)) (o:(Int => Int))(n:Int)
= if (i(n)) e(n) else o(n)
you can now define c as a Int=>Int by leaving out the last parameter n to construct6. In the REPL:
scala> def c: Int => Int = construct6(isEven)(dec)(inc)
c: Int => Int
scala> c(8)
res0: Int = 4
which I believe is what you were trying to do.
If you want to infer c's type instead of specifying it as a Int => Int explicitly) you will have to use the omnipresent _ to confirm to Scala that you're not just leaving out anything by mistake:
scala> def c2= construct6(isEven)(dec)(inc) _
c2: Int => Int
scala> c2(8)
res1: Int = 4
I am wondering if it is possible to use currying on multi parameter-group functions :
scala> def sum(a: Int)(b: Int): Int = { a+b }
sum: (a: Int)(b: Int)Int
scala> sum(3)(4)
res2: Int = 7
scala> val partFunc = sum(3) _
partFunc: Int => Int = <function1>
scala> partFunc(4)
res3: Int = 7
scala> val partFunc2 = sum _ _
<console>:1: error: ';' expected but '_' found.
val partFunc2 = sum _ _
^
scala> val partFunc2 = (sum _) _
<console>:8: error: _ must follow method; cannot follow Int => (Int => Int)
val partFunc2 = (sum _) _
Writing simply sum _ does not yet have anything to do with the arguments of sum, but simply distinguishes the function object sum from an application of the function.
Hence, you can write:
scala> val partFunc2 = sum _
partFunc2: Int => (Int => Int) = <function1>
As you can see from the type information, this is already the curried version of sum which takes two Int parameters.
Of course, you can then proceed as before with partFunc2(4) being of type Int => Int and so on.
You can do it like this:
val partFunc2 = sum _
or like this:
val partFunc2 = sum(3) _
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(_)(_)