What's the meaning of -> in scala - scala

When I read the book 《Functional Programming in scala》.
I find the expression like this:
case (Cons(h, t), Empty) =>
Some(f(Some(h()), Option.empty[B]) -> (t(), empty[B]))
What's the difference between
Some(f(Some(h()), Option.empty[B]), (t(), empty[B]))

If your 2nd example compiles, it should compile with a warning: creating a 2-tuple: this may not be what you want Otherwise it would fail because Some() doesn't take two parameters. The 1st example should compile because the -> is explicitly creating the tuple to send as a single parameter to the (outer) Some().
When creating a tuple of two elements you have the option of using parentheses and comma (5, true), or the arrow 5 -> true. In most situations the parentheses are optional when using the arrow version.
The arrow can't be used if you want more than 2 elements (i.e. not nested tuples):
'c' -> 'b' -> 'x'
//res0: ((Char, Char), Char) = ((c,b),x)

The -> is actually a method of the ArrowAssoc class to which every object can be implicitly converted. See the object scala.Predef. It is defined as:
def -> [B](y: B): Tuple2[A, B] = Tuple2(x, y)
This means that 1 -> 2 is equivalent to 1.->(2) which evaluates to Tuple2(1, 2). This is also explained in section 21.4 of the book (3rd edition).

Related

Map data type creation

What does this expression do?
val m = Map(1 -> 2, 2 -> 4)
This is the return value:
scala.collection.immutable.Map[Int, Int] = Map(1 -> 2, 2 -> 4)
What does this expression do?
Note: this is not an expression, it is a value definition. A val definition does not have a value.
The part after the = sign is an expression, though.
val m = Map(1 -> 2, 2 -> 4)
In Scala, foo(bar) can mean one of two things:
calling the method foo implicitly on this passing bar as an argument.
calling the method apply on the object obtained by evaluating the expression foo passing bar as an argument.
So, foo(bar) is equivalent to either
this.foo(bar)
or
foo.apply(bar)
depending on which is available in the current scope.
In this particular case, there is no method named Map defined in the current scope, it corresponds to the second meaning:
Map.apply(1 -> 2, 2 -> 4)
Where does Map come from? This is actually scala.Predef.Map, which is defined in scala.Predef which is an object that gets automatically imported into every Scala program. Note: don't confuse the value scala.Predef.Map which is an alias for the object scala.collection.immutable.Map with the type alias scala.Predef.Map[A, B] which is an alias for the trait scala.collection.immutable.Map.
Values and types live in completely separate universes in Scala (like in most other programming languages), therefore it is perfectly possible for them to have the same name, since they can never appear in the same context and thus there can never be an ambiguity.
So, let's look at the documentation for Map.apply to tell us what it does:
def apply[A, B](elems: (A, B)*): Map[A, B]
A collection of type Map that contains given key/value bindings.
So, Map.apply returns a Map that contains the key/value pairs that we pass as arguments. But wait, apply takes repeated parameters of type (A, B) (which is syntactic sugar for Tuple2[A, B]), but we are not passing a Tuple2, i.e. we are not passing (1, 2), (2, 4) as arguments but rather 1 -> 2, 2 -> 4, so what is this?
Remember that in Scala, a much wider range of identifiers is allowed than in many other languages. Also remember that methods can be called without a period, and that if a method is called without a period and you are passing only a single argument, you can leave out the parentheses. So,
1 -> 2
is the same as
1 ->(2)
is the same as
1.->(2)
All this does is call the method -> (which is just a boring standard Scala method name, nothing at all special about it) on 1 passing 2 as the argument. Now, it turns out that Int doesn't have a -> method, but there is an implicit class ArrayAssoc which adds the methods -> as well as → to Any type and … tadaaa … returns a Tuple2[A, B].
Alright. Putting it all together:
1 -> 2
is the same as
1 ->(2)
is the same as
1.->(2)
which is actually calling ArrowAssoc.-> which returns
(1, 2)
which is syntactic sugar for
new Tuple2(1, 2)
(and the same for 2 -> 4) which we are passing to
Map(new Tuple2(1, 2), new Tuple2(3, 4))
which is actually
scala.Predef.Map(new Tuple2(1, 2), new Tuple2(3, 4))
which is assigned to
scala.collection.immutable.Map(new Tuple2(1, 2), new Tuple2(3, 4))
which is actually
scala.collection.immutable.Map.apply(new Tuple2(1, 2), new Tuple2(3, 4))
which returns a new instance of some unspecified implementation class of the trait scala.collection.immutable.Map[Int, Int] with the key 1 associated with the value 2 and the key 2 associated with the value 4.
This is the return value:
scala.collection.immutable.Map[Int, Int] = Map(1 -> 2, 2 -> 4)
To be pedantic: this is the string representation of the return value, obtained by calling toString() on it. Map overrides toString() and represents its contents using the same -> that could be used to construct it.
a -> b is syntactic sugar for creating a tuple (a, b).
The scala Map constructor takes an arbitrary number of tuples (a, b) as arguments and creates a mapping from the first element of each tuple to the second. In your case, since you are populating it with integers, it generates a Map[Int, Int]: A mapping from integers to integers.
You can now use your map e.g. as follows:
m(1) // Has value 2
m(2) // Has value 4

Transforming Map using map in scala

Given a string I want to create a map that for each character in a string will give the number of times the character occurs in a string. The following function makes a map from character to a list of Strings.
def wordOccurrences(w: String) = {
val lower = w.toLowerCase.toList
lower.groupBy(t => t)
}
Now I wanted to alter the last line to:
lower.groupBy(t => t) map ( (x,y) => x -> y.length)
But it doesn't work, can someone explain why and how to fix it?
For mapping purposes, a Map[K, V] is an Iterable[(K, V)] (notice the extra pair of parentheses, identifying a tuple type), meaning that when you map over it you have pass a function that goes from (K, V) to your target type.
What you are doing, however, is passing a function that takes two independent arguments, rather then a single tuple argument.
The difference can be seen by inspecting the types of these two functions in the Scala shell:
scala> :t (a: Int, b: Int) => a + b
(Int, Int) => Int
scala> :t (p: (Int, Int)) => p._1 + p._2
((Int, Int)) => Int
Notice how the former takes two arguments while the latter takes a single tuple.
What you can do is pass a function which decomposes the tuple so that you can bind the components of the tuple independently:
lower.groupBy(t => t) map { case (x, y) => x -> y.length }
or alternatively pass a function which uses the tuple without deconstructing it
lower.groupBy(t => t) map (p => p._1 -> p._2.length)
Note
Dotty, which is the current project Scala's original author Martin Odersky is working on and that will probably become Scala 3, supports the syntax you are proposing, calling the feature function arity adaptation. This has been discussed, along with other feature, in Odersky's 2016 Keynote at Scala eXchange, "From DOT to Dotty" (here the video taped at 2017 Voxxed Days CERN).
You can use
lower.groupBy(t => t).mapValues(_.length)

Scala operator associativity (2nd parameter lists)

Is it possible to call an apply function directly on the result of a method which takes a second parameter list (with an implicit arg)? Even with parentheses in the logical place, I get the same compile-time type error, which indicates it doesn't parse it as expected.
val x = Map(1 -> 2, 2->4, 3-> 6) //1
val y = x.map(_.swap) //2
y(4) //3
x.map(_.swap)(4) //4
((x.map(_.swap))(4) //5
Line 4 makes sense to not parse since the (4) easily appears to be the second parameter list for map(), but line 5, there is a set of ()'s around the .map expression, yet it still associates the (4) to the .map rather than the result of .map().
Is there a way to do lines 2 and 3 in one expression?
EDIT: I'm aware of .apply(), which is what the compiler will insert itself. Is there a way to do this without manually de-sugaring?
Yes there are several possible solutions.
All work by either satisfying the implicit parameter list or giving the compiler a hint that expression has ended and the (), read apply, is really the apply-method and no second argument list.
1. Calling .apply()
scala> Map(1 -> 2, 2 -> 4, 3 -> 6).map(_.swap).apply(4)
res7: Int = 2
2. Supplying the implicit directly
Another option is supplying the implicit directly
Example with breakout
import scala.collection.breakOut
scala> List(1).map(_ + 1)(breakOut)(0)
res38: Int = 2
I think the general problem is: You have to fill to provide the implicit for the CanBuildFrom to work properly or explicitly state that you want to call apply and not fill the second parameter list.
You can find more in http://docs.scala-lang.org/tutorials/FAQ/breakout. Opposing to the name the secCanBuildFrom works.

Adding an (Int, Int) tuple to a Set in scala [duplicate]

Are the parenthesis around the final tuple really needed? It doesn't compile without them and the compiler tries to add only the Sort("time") and complains that it expects a tuple instead.
val maxSortCounts: Map[Sort, Int] =
sorts.map(s => s -> usedPredicates.map(pred => pred.signature.count(_ == s)).max)
.toMap + ((Sort("time"), 1))
I've tried to reproduce this behaviour inside the REPL with a shorter example, but there it behaves as intended. The variable sorts is a Seq[Sort].
error: type mismatch;
found : <snip>.Sort
required: (<snip>.Sort, Int)
.toMap + (Sort("time"), 1)
Yes, they are needed. Otherwise the compiler will interpret the code as
x.+(y, z) instead of x.+((y, z)).
Instead, you can use ArrowAssoc again: x + (y -> z). Notice, the parentheses are also needed because + and - have the same precedence (only the first sign of a method defines its precedence).
Yes, they're needed. They make the expression a tuple. Parentheses surrounding a comma-separated list create tuple objects. For example, (1, 2, 3) is a 3-tuple of numbers.
Map's + method accepts a pair - in other words a tuple of two elements. Map represents entries in the map as (key,value) tuples.

Cannot create apply function with static language?

I have read that with a statically typed language like Scala or Haskell there is no way to create or provide a Lisp apply function:
(apply #'+ (list 1 2 3)) => 6
or maybe
(apply #'list '(list :foo 1 2 "bar")) => (:FOO 1 2 "bar")
(apply #'nth (list 1 '(1 2 3))) => 2
Is this a truth?
It is perfectly possible in a statically typed language. The whole java.lang.reflect thingy is about doing that. Of course, using reflection gives you as much type safety as you have with Lisp. On the other hand, while I do not know if there are statically typed languages supporting such feature, it seems to me it could be done.
Let me show how I figure Scala could be extended to support it. First, let's see a simpler example:
def apply[T, R](f: (T*) => R)(args: T*) = f(args: _*)
This is real Scala code, and it works, but it won't work for any function which receives arbitrary types. For one thing, the notation T* will return a Seq[T], which is a homegenously-typed sequence. However, there are heterogeneously-typed sequences, such as the HList.
So, first, let's try to use HList here:
def apply[T <: HList, R](f: (T) => R)(args: T) = f(args)
That's still working Scala, but we put a big restriction on f by saying it must receive an HList, instead of an arbitrary number of parameters. Let's say we use # to make the conversion from heterogeneous parameters to HList, the same way * converts from homogeneous parameters to Seq:
def apply[T, R](f: (T#) => R)(args: T#) = f(args: _#)
We aren't talking about real-life Scala anymore, but an hypothetical improvement to it. This looks reasonably to me, except that T is supposed to be one type by the type parameter notation. We could, perhaps, just extend it the same way:
def apply[T#, R](f: (T#) => R)(args: T#) = f(args: _#)
To me, it looks like that could work, though that may be naivety on my part.
Let's consider an alternate solution, one depending on unification of parameter lists and tuples. Let's say Scala had finally unified parameter list and tuples, and that all tuples were subclass to an abstract class Tuple. Then we could write this:
def apply[T <: Tuple, R](f: (T) => R)(args: T) = f(args)
There. Making an abstract class Tuple would be trivial, and the tuple/parameter list unification is not a far-fetched idea.
A full APPLY is difficult in a static language.
In Lisp APPLY applies a function to a list of arguments. Both the function and the list of arguments are arguments to APPLY.
APPLY can use any function. That means that this could be any result type and any argument types.
APPLY takes arbitrary arguments in arbitrary length (in Common Lisp the length is restricted by an implementation specific constant value) with arbitrary and possibly different types.
APPLY returns any type of value that is returned by the function it got as an argument.
How would one type check that without subverting a static type system?
Examples:
(apply #'+ '(1 1.4)) ; the result is a float.
(apply #'open (list "/tmp/foo" :direction :input))
; the result is an I/O stream
(apply #'open (list name :direction direction))
; the result is also an I/O stream
(apply some-function some-arguments)
; the result is whatever the function bound to some-function returns
(apply (read) (read))
; neither the actual function nor the arguments are known before runtime.
; READ can return anything
Interaction example:
CL-USER 49 > (apply (READ) (READ)) ; call APPLY
open ; enter the symbol OPEN
("/tmp/foo" :direction :input :if-does-not-exist :create) ; enter a list
#<STREAM::LATIN-1-FILE-STREAM /tmp/foo> ; the result
Now an example with the function REMOVE. We are going to remove the character a from a list of different things.
CL-USER 50 > (apply (READ) (READ))
remove
(#\a (1 "a" #\a 12.3 :foo))
(1 "a" 12.3 :FOO)
Note that you also can apply apply itself, since apply is a function.
CL-USER 56 > (apply #'apply '(+ (1 2 3)))
6
There is also a slight complication because the function APPLY takes an arbitrary number of arguments, where only the last argument needs to be a list:
CL-USER 57 > (apply #'open
"/tmp/foo1"
:direction
:input
'(:if-does-not-exist :create))
#<STREAM::LATIN-1-FILE-STREAM /tmp/foo1>
How to deal with that?
relax static type checking rules
restrict APPLY
One or both of above will have to be done in a typical statically type checked programming language. Neither will give you a fully statically checked and fully flexible APPLY.
The reason you can't do that in most statically typed languages is that they almost all choose to have a list type that is restricted to uniform lists. Typed Racket is an example for a language that can talk about lists that are not uniformly typed (eg, it has a Listof for uniform lists, and List for a list with a statically known length that can be non-uniform) -- but still it assigns a limited type (with uniform lists) for Racket's apply, since the real type is extremely difficult to encode.
It's trivial in Scala:
Welcome to Scala version 2.8.0.final ...
scala> val li1 = List(1, 2, 3)
li1: List[Int] = List(1, 2, 3)
scala> li1.reduceLeft(_ + _)
res1: Int = 6
OK, typeless:
scala> def m1(args: Any*): Any = args.length
m1: (args: Any*)Any
scala> val f1 = m1 _
f1: (Any*) => Any = <function1>
scala> def apply(f: (Any*) => Any, args: Any*) = f(args: _*)
apply: (f: (Any*) => Any,args: Any*)Any
scala> apply(f1, "we", "don't", "need", "no", "stinkin'", "types")
res0: Any = 6
Perhaps I mixed up funcall and apply, so:
scala> def funcall(f: (Any*) => Any, args: Any*) = f(args: _*)
funcall: (f: (Any*) => Any,args: Any*)Any
scala> def apply(f: (Any*) => Any, args: List[Any]) = f(args: _*)
apply: (f: (Any*) => Any,args: List[Any])Any
scala> apply(f1, List("we", "don't", "need", "no", "stinkin'", "types"))
res0: Any = 6
scala> funcall(f1, "we", "don't", "need", "no", "stinkin'", "types")
res1: Any = 6
It is possible to write apply in a statically-typed language, as long as functions are typed a particular way. In most languages, functions have individual parameters terminated either by a rejection (i.e. no variadic invocation), or a typed accept (i.e. variadic invocation possible, but only when all further parameters are of type T). Here's how you might model this in Scala:
trait TypeList[T]
case object Reject extends TypeList[Reject]
case class Accept[T](xs: List[T]) extends TypeList[Accept[T]]
case class Cons[T, U](head: T, tail: U) extends TypeList[Cons[T, U]]
Note that this doesn't enforce well-formedness (though type bounds do exist for that, I believe), but you get the idea. Then you have apply defined like this:
apply[T, U]: (TypeList[T], (T => U)) => U
Your functions, then, are defined in terms of type list things:
def f (x: Int, y: Int): Int = x + y
becomes:
def f (t: TypeList[Cons[Int, Cons[Int, Reject]]]): Int = t.head + t.tail.head
And variadic functions like this:
def sum (xs: Int*): Int = xs.foldLeft(0)(_ + _)
become this:
def sum (t: TypeList[Accept[Int]]): Int = t.xs.foldLeft(0)(_ + _)
The only problem with all of this is that in Scala (and in most other static languages), types aren't first-class enough to define the isomorphisms between any cons-style structure and a fixed-length tuple. Because most static languages don't represent functions in terms of recursive types, you don't have the flexibility to do things like this transparently. (Macros would change this, of course, as well as encouraging a reasonable representation of function types in the first place. However, using apply negatively impacts performance for obvious reasons.)
In Haskell, there is no datatype for multi-types lists, although I believe, that you can hack something like this together whith the mysterious Typeable typeclass. As I see, you're looking for a function, which takes a function, a which contains exactly the same amount of values as needed by the function and returns the result.
For me, this looks very familiar to haskells uncurryfunction, just that it takes a tuple instead of a list. The difference is, that a tuple has always the same count of elements (so (1,2) and (1,2,3) are of different types (!)) and there contents can be arbitrary typed.
The uncurry function has this definition:
uncurry :: (a -> b -> c) -> (a,b) -> c
uncurry f (a,b) = f a b
What you need is some kind of uncurry which is overloaded in a way to provide an arbitrary number of params. I think of something like this:
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
class MyApply f t r where
myApply :: f -> t -> r
instance MyApply (a -> b -> c) (a,b) c where
myApply f (a,b) = f a b
instance MyApply (a -> b -> c -> d) (a,b,c) d where
myApply f (a,b,c) = f a b c
-- and so on
But this only works, if ALL types involved are known to the compiler. Sadly, adding a fundep causes the compiler to refuse compilation. As I'm not a haskell guru, maybe domeone else knows, howto fix this. Sadly, I don't know how to archieve this easier.
Résumee: apply is not very easy in Haskell, although possible. I guess, you'll never need it.
Edit I have a better idea now, give me ten minutes and I present you something whithout these problems.
try folds. they're probably similar to what you want. just write a special case of it.
haskell: foldr1 (+) [0..3] => 6
incidentally, foldr1 is functionally equivalent to foldr with the accumulator initialized as the element of the list.
there are all sorts of folds. they all technically do the same thing, though in different ways, and might do their arguments in different orders. foldr is just one of the simpler ones.
On this page, I read that "Apply is just like funcall, except that its final argument should be a list; the elements of that list are treated as if they were additional arguments to a funcall."
In Scala, functions can have varargs (variadic arguments), like the newer versions of Java. You can convert a list (or any Iterable object) into more vararg parameters using the notation :_* Example:
//The asterisk after the type signifies variadic arguments
def someFunctionWithVarargs(varargs: Int*) = //blah blah blah...
val list = List(1, 2, 3, 4)
someFunctionWithVarargs(list:_*)
//equivalent to
someFunctionWithVarargs(1, 2, 3, 4)
In fact, even Java can do this. Java varargs can be passed either as a sequence of arguments or as an array. All you'd have to do is convert your Java List to an array to do the same thing.
The benefit of a static language is that it would prevent you to apply a function to the arguments of incorrect types, so I think it's natural that it would be harder to do.
Given a list of arguments and a function, in Scala, a tuple would best capture the data since it can store values of different types. With that in mind tupled has some resemblance to apply:
scala> val args = (1, "a")
args: (Int, java.lang.String) = (1,a)
scala> val f = (i:Int, s:String) => s + i
f: (Int, String) => java.lang.String = <function2>
scala> f.tupled(args)
res0: java.lang.String = a1
For function of one argument, there is actually apply:
scala> val g = (i:Int) => i + 1
g: (Int) => Int = <function1>
scala> g.apply(2)
res11: Int = 3
I think if you think as apply as the mechanism to apply a first class function to its arguments, then the concept is there in Scala. But I suspect that apply in lisp is more powerful.
For Haskell, to do it dynamically, see Data.Dynamic, and dynApp in particular: http://www.haskell.org/ghc/docs/6.12.1/html/libraries/base/Data-Dynamic.html
See his dynamic thing for haskell, in C, void function pointers can be casted to other types, but you'd have to specify the type to cast it to. (I think, haven't done function pointers in a while)
A list in Haskell can only store values of one type, so you couldn't do funny stuff like (apply substring ["Foo",2,3]). Neither does Haskell have variadic functions, so (+) can only ever take two arguments.
There is a $ function in Haskell:
($) :: (a -> b) -> a -> b
f $ x = f x
But that's only really useful because it has very low precedence, or as passing around HOFs.
I imagine you might be able to do something like this using tuple types and fundeps though?
class Apply f tt vt | f -> tt, f -> vt where
apply :: f -> tt -> vt
instance Apply (a -> r) a r where
apply f t = f t
instance Apply (a1 -> a2 -> r) (a1,a2) r where
apply f (t1,t2) = f t1 t2
instance Apply (a1 -> a2 -> a3 -> r) (a1,a2,a3) r where
apply f (t1,t2,t3) = f t1 t2 t3
I guess that's a sort of 'uncurryN', isn't it?
Edit: this doesn't actually compile; superseded by #FUZxxl's answer.