This question already has answers here:
Scala underscore minimal function
(3 answers)
Closed 4 years ago.
Could someone show me the difference between the 2 implementations of function sequence in my code.
I'm using IntelIJ IDEA with sbt.
def traverse[A, B](a : List[A]) (f : A => Option[B]) : Option[List[B]] = {
a.foldRight(Some(List[B]()) : Option[List[B]])(
(x, y) => for {
xx <- f(x)
yy <- y
} yield xx +: yy
)
}
def sequence[A](a: List[Option[A]]): Option[List[A]] = {
traverse(a)(x => x) //worked
//traverse(a)(_) //Expression of type (Option[A] => Option[B_]) => Option[List[Nothing]] doesn't conform to expected type Option[List[A]]
}
I expected the final line to achieve the same, instead it show that I return an Option[List[Nothing]].
TL;DR, f(_) does not equal f(x => x)
As eloquently explained in this relevant SO answer, you're looking at the difference between the "short form" for anonymous function versus partially applied function.
When _ is part of an expression that represents a parameter:
f(_ + 1) // f(x => x + 1)
g(2 * _) // g(x => 2 * x)
When _ is a parameter by itself:
f(_) // x => f(x)
g(1, _) // x => g(1, x)
h(0)(_) // x => h(0)(x)
Related
Given Scala 2.12.6:
val list = List(1)
val x = 2
This works:
list.map ( y => x + y )
returning List[Int] = List(3)
and this works:
list.map ( (y: Int) => x + y )
returning the same value.
Same for this:
list.map { (y: Int) => x + y }
And same for this:
list.map { y: Int => x + y }
Yet this fails:
list.map ( y: Int => x + y )
producing the error:
error: not found: type +
list.map ( y: Int => x + y )
^
Why is Scala thinking the + is meant to indicate a type, and where is this difference between using parenthesis and curly braces documented and explained?
The Section 6.23 about anonymous functions says:
In the case of a single untyped formal parameter, (x) => e can be abbreviated to x => e. If an anonymous function (x: T) => e with a single typed parameter appears as the result expression of a block, it can be abbreviated to x: T => e.
Thus, in a block { ... }, the function literal (y: Int) => x + y can be abbreviated to just y: Int => x + y.
Without the block, the entire Int => x + y-part is treated as type ascription, so the error message actually makes sense. For example, here is a context in which the offending expression becomes valid:
type y = Unit
type x = Unit
type +[A, B] = Int
val y = (i: Int) => 42 + i
val list = List(1)
println(
list.map ( y: Int => x + y )
) // happily prints `List(43)`.
This is because there are two ys in two separate scopes (one value, one type alias), so that (y: Int => x + y) becomes (y: Int => +[x, y]), and then (y: Int => Int), which is just a type ascription enforcing that value y is indeed of function type Int => Int (which it is, so everything compiles and runs). Here is another similar example.
My suggestion: stick to the slightly more verbose (foo: Foo) => { ... } notation, it will cause fewer surprises for everyone who tries to read and to modify the code. Otherwise there is some risk that
argument types in bindings collide with type ascriptions
=> of the anonymous lambda collides with function type =>
arithmetic operation + collides with binary infix type constructor +[_,_]
values x, y collide with undefined types x, y.
The fact that same syntax can denote both types and expressions can be somewhat of a double-edged sword.
OK, so I'm trying to implement the basics of lambda calculus. Here it goes.
My numbers:
def zero[Z](s: Z => Z)(z: Z): Z = z
def one[Z](s: Z => Z)(z: Z): Z = s(z)
def two[Z](s: Z => Z)(z: Z): Z = s(s(z))
Partially (actually, non) applied version of them is smth like that:
def z[Z]: (Z => Z) => (Z => Z) = zero _
Before I continue I define some types:
type FZ[Z] = Z => Z
type FFZ[Z] = FZ[Z] => FZ[Z]
Fine, succ function goes like (Application order should be exactly like that! I took the definition here):
def succ[Z](w: FFZ[Z])(y: FZ[Z])(x: Z): Z = y((w(y))(x))
And the unapplied version of it gets as scary as:
def s[Z]: FFFZ[Z] = successor _
Beg your pardon, here is the missing types:
type FFFZ[Z] = FFZ[Z] => FFZ[Z]
type FFFFZ[Z] = FFFZ[Z] => FFFZ[Z]
But I'm stuck at the add function. If conformed to types and definition (taken here as well) it goes like
def add[Z](a: FFFFZ[Z])(b: FFZ[Z]): FFZ[Z] =
(a(s))(b)
But I want a to be a common number of type FFZ[Z].
So -- how can I define addition?
It's totally possible to implement Church numerals in Scala. Here is one such rather straight-forward implementation:
object ChurchNumerals {
type Succ[Z] = Z => Z
type ChNum[Z] = Succ[Z] => Z => Z
def zero[Z]: ChNum[Z] =
(_: Succ[Z]) => (z: Z) => z
def succ[Z] (num: ChNum[Z]): ChNum[Z] =
(s: Succ[Z]) => (z: Z) => s( num(s)(z) )
// a couple of church constants
def one[Z] : ChNum[Z] = succ(zero)
def two[Z] : ChNum[Z] = succ(one)
// the addition function
def add[Z] (a: ChNum[Z]) (b: ChNum[Z]) =
(s: Succ[Z]) => (z: Z) => a(s)( b(s)(z) )
def four[Z] : ChNum[Z] = add(two)(two)
// test
def church_to_int (num: ChNum[Int]): Int =
num((x: Int) => x + 1)(0)
def fourInt: Int = church_to_int(four)
def main(args: Array[String]): Unit = {
println(s"2 + 2 = ${fourInt}")
}
}
Compiles and prints:
$ scala church-numerals.scala
2 + 2 = 4
If I were to explain Church numerals from scratch I'd add more commentaries. But taking the context into account, I'm not sure on what to comment in this case. Please feel free to ask and I'll add more explanations.
I have coded Numerals, Booleans and Pairs: https://github.com/pedrofurla/church/blob/master/src/main/scala/Church.scala following Church's style.
One thing I noticed is that using the curried function syntax was much easier than using multiple argument lists. Some of the interesting snippets
type NUM[A] = (A => A) => A => A
def succ [A]: NUM[A] => NUM[A] = m => n => x => n(m(n)(x))
def zero [A]: NUM[A] = f => x => x
def one [A]: NUM[A] = f => x => f(x)
def two [A]: NUM[A] = f => x => f(f(x))
def three [A]: NUM[A] = f => x => f(f(f(x)))
def plus [A]: (NUM[A]) => (NUM[A]) => NUM[A] = m => n => f => x => m(f)(n(f)(x))
Now for printing them out (very similar to Antov Trunov's solution):
def nvalues[A] = List(zero[A], one[A], two[A], three[A])
val inc: Int => Int = _ + 1
def num: (NUM[Int]) => Int = n => n(inc)(0)
def numStr: (NUM[String]) => String = n => n("f (" + _ + ") ")("z")
Some output:
scala> println(nvalues map num)
List(0, 1, 2, 3)
scala> println(nvalues map numStr) // Like this better :)
List(z, f (z) , f (f (z) ) , f (f (f (z) ) ) )
I've a question regarding this pattern matching in scala:
val div: (Double, Double) => Double = {
case (x, y) if y != 0 => x / y
}
I've understand how pattern matching works and its syntaxis in scala, but this expression drives me crazy. How does complier knows that x and y is an arguments of the function and pattern match on them?
The rules for this are defined in section 8.5 "Pattern Matching Anonymous Functions" of the Scala Language Specification. If using an anonymous function with pattern matching, the type must be partially provided. You do that by saying the type is (Double, Double) => Double, which is shorthand for Function2[Double, Double, Double].
Now:
If the expected type is scala.Function k [S1,…,Sk, R], the expression is taken to be equivalent to the anonymous function:
(x1:S1,…,xk:Sk) => (x1,…,xk) match {
case p1 => b1 … case pn => bn
}
So no matter what the arity of your function, the pattern match is passed a tuple of the function's arguments, hence you can use the regular tuple extractor syntax.
So your example is short for
val div: (Double, Double) => Double = (a, b) => (a, b) match {
case (x, y) if y != 0 => x / y
}
or
val div = (a: Double, b: Double) => (a, b) match {
case (x, y) if y != 0 => x / y
}
The naming of the extractor parameters x and y is up to your imagination. You decide how to call the resulting elements of the extractor, you could as well write case (foo, bar) => ...
As far as I know, the infix operator usage in Scala should be equivalent to the invocation of a method. So:
scala> "a" + 3.toString
res0: java.lang.String = a3
Is the same as:
scala> "a".+(3.toString)
res1: java.lang.String = a3
I came across an occasion where this is not happening, when there is a placeholder. I was doing something more complex, but it can be distilled to:
scala> def x(f:(Int)=>String) = f(3)
x: (f: Int => String)String
scala> x("a" + _.toString)
res3: String = a3
So far so good. But...
scala> x("a".+(_.toString))
<console>:9: error: missing parameter type for expanded function ((x$1) => x$1.toString)
x("a".+(_.toString))
What's the difference here? What am I missing?
Jordi
The _ placeholder can only appear at the topmost Expr in its function. That means
(_.toString)
is itself a function, and "a" + some function of unknown type doesn't make much sense to the compiler.
Your assessment of infix notation is correct, but your understanding of placeholder parameters is flawed.
When you use underscore as a placeholder parameter, you are creating a function. The question is what are the boundaries of that function: where does it start, where does it end? For example, consider this expression:
_ + _ + _
How should it be translated? Here are some alternatives:
(x, y, z) => { x + y + z }
(x, y) => { (z) => { x + y } + z }
(x) => { x + { (y, z) => y + z } }
Well, Scala rule is that the scope is the innermost parenthesis-delimited expression, or the whole expression otherwise. So, in practice, you wrote two different things:
x("a" + _.toString) // is the same thing as
x((y) => "a" + y.toString)
x("a".+(_.toString)) // is the same thing as
x("a".+((y) => y.toString))
I read in Programming in Scala section 23.5 that map, flatMap and filter operations can always be converted into for-comprehensions and vice-versa.
We're given the following equivalence:
def map[A, B](xs: List[A], f: A => B): List[B] =
for (x <- xs) yield f(x)
I have a value calculated from a series of map operations:
val r = (1 to 100).map{ i => (1 to 100).map{i % _ == 0} }
.map{ _.foldLeft(false)(_^_) }
.map{ case true => "open"; case _ => "closed" }
I'm wondering what this would look like as a for-comprehension. How do I translate it?
(If it's helpful, in words this is:
take integers from 1 to 100
for each, create a list of 100 boolean values
fold each list with an XOR operator, back into a boolean
yield a list of 100 Strings "open" or "closed" depending on the boolean
I imagine there is a standard way to translate map operations and the details of the actual functions in them is not important. I could be wrong though.)
Is this the kind of translation you're looking for?
for (i <- 1 to 100;
val x = (1 to 100).map(i % _ == 0);
val y = x.foldLeft(false)(_^_);
val z = y match { case true => "open"; case _ => "closed" })
yield z
If desired, the map in the definition of x could also be translated to an "inner" for-comprehension.
In retrospect, a series of chained map calls is sort of trivial, in that you could equivalently call map once with composed functions:
s.map(f).map(g).map(h) == s.map(f andThen g andThen h)
I find for-comprehensions to be a bigger win when flatMap and filter are involved. Consider
for (i <- 1 to 3;
j <- 1 to 3 if (i + j) % 2 == 0;
k <- 1 to 3) yield i ^ j ^ k
versus
(1 to 3).flatMap { i =>
(1 to 3).filter(j => (i + j) % 2 == 0).flatMap { j =>
(1 to 3).map { k => i ^ j ^ k }
}
}