Cannot prove that Unit <:< (T, U) - scala

When trying to remove all Unit - () from a list, I tried to call toMap.
scala> List((), ()).filter(_ != ()).toMap
<console>:8: error: Cannot prove that Unit <:< (T, U).
List((), ()).filter(_ != ()).toMap
^
What does this error mean?
For a List, I'd like to create a map of all tuples (String, String) for non-Unit elements, but some of the values can be null.
scala> val x = List((), (), (3,4)).filter(_ != ()).toMap
<console>:7: error: Cannot prove that Any <:< (T, U).
val x = List((), (), (3,4)).filter(_ != ()).toMap
^
scala> val x = List((), (), (3,4)).filter(_ != ())
x: List[Any] = List((3,4))
scala> x.toMap
<console>:9: error: Cannot prove that Any <:< (T, U).
x.toMap
^

Ah! Now your other question makes a little more sense. Still not sure what you're doing to produce this mixed Unit/Tuple2 list though.
This should work:
List((), (), (3,4)).collect { case t#(_: Int, _: Int) => t }.toMap
Note that I'm using variable binding here (binding the match to t) to return the same Tuple2 instance we matched rather than creating a new one.
By using collect you convert the type of your list from List[Any] to List[(Int, Int)], which is what toMap wants since it's expecting some List[(A,B)].
Note: Although this answer should work for you, I still think your design is flawed. You'd be better off fixing the underlying design flaw rather than treating the symptoms like this.
It looks like this would be a good fit for using Scala's Option type. In this case, your sample list would become List(None, None, Some((3,4))), or you could write it as List(None, None, Some(3->4)) for readability (nested parenthesis like that can get confusing).
If you use Option then the type of your list becomes List[Option[(Int, Int)]], which should be much nicer to deal with than a List[Any]. To get rid of the None entries and get the desired List[(Int,Int)] you can just call flatten:
List(None, None, Some(3->4)).flatten
// res0: List[(Int, Int)] = List((3,4))
List(None, None, Some(3->4)).flatten.toMap
// res1: scala.collection.immutable.Map[Int,Int] = Map(3 -> 4)
However, it would be even better if you can avoid putting the None entries in your list in the first place. If you're producing this list using a Scala for comprehension, you could use a guard in your for expression to remove the invalid elements from the output.

It means that the type of an element in the list can't be viewed as a tuple which is required to build a Map. A Map in a sense is a collection of tuples (and more).
Illustration:
scala> List(1).toMap
<console>:8: error: Cannot prove that Int <:< (T, U).
List(1).toMap
^
scala> List(1 -> 2).toMap
res1: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
I can build a map from a list of tuples, but not from a list of single cardinality elements.
Maybe you mean to say .map instead of .toMap? ;)

All in one go:
scala> val l2 = List(1 -> 3, (), 4 -> 4, (), 9 -> 4, (), 16 -> 7)
l2: List[Any] = List((1,3), (), (4,4), (), (9,4), (), (16,7))
scala> (l2 collect { case (a, b) => (a, b) }).toMap
res4: scala.collection.immutable.Map[Any,Any] = Map(1 -> 3, 4 -> 4, 9 -> 4, 16 -> 7)
Better typed:
scala> (l2 collect { case (i: Int, j: Int) => (i, j) }).toMap
res5: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 4 -> 4, 9 -> 4, 16 -> 7)

Related

scala map function of map vs. list

Snippet 1:
val l = List(1,2,43,4)
l.map(i => i *2)
Snippet 2:
val s = "dsadadaqer12"
val g = s.groupBy(c=>c)
g.map ( {case (c,s) => (c,s.length)})
In snippet #2, the syntax different than #1 , i.e. curly braces required -- why?
I thought the following would compile, but it does not:
g.map ( (c,s) => (c,s.length))
Can someone explain why?
Thanks
The difference between the two is - the latter uses Pattern Matching and the former doesn't.
The syntax g.map({case (c,s) => (c,s.length)}) is just syntax sugar for:
g.map(v => v match { case (c,s) => (c,s.length) })
Which means: we name the input argument of our anonymous function v, and then in the function body we match it to a tuple (c,s). Since this is so useful, Scala provides the shorthand version you used.
Of course - this doesn't really have anything to do with whether you use a Map or a List - consider all the following possibilities:
scala> val l = List(1,2,43,4)
l: List[Int] = List(1, 2, 43, 4)
scala> l.map({ case i => i*2 })
res0: List[Int] = List(2, 4, 86, 8)
scala> val l2 = List((1,2), (3,4))
l2: List[(Int, Int)] = List((1,2), (3,4))
scala> l2.map({ case (i, j) => i*j })
res1: List[Int] = List(2, 12)
scala> val g = Map(1 -> 2, 3 -> 4)
g: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 4)
scala> g.map(t => t._1 * t._2)
res2: scala.collection.immutable.Iterable[Int] = List(2, 12)
Both Map and List can use both syntax options, depending mostly on what you actually want to do.
1- g.map{case (c,s) => (c,s.length)}
2- g.map((c,s) => (c,s.length))
The map method pulls a single argument, a 2-tuple, from the g collection. The 1st example compiles because the case statement uses pattern matching to extract the tuple's elements whereas the 2nd example doesn't and it won't compile. For that you'd have to do something like: g.map(t => (t._1, t._2.length))
As for the parenthesis vs. curly braces: braces have always been required for "partial functions," which is what that case statement is. You can use either braces or parens for anonymous functions (i.e. x => ...) although you are required to use braces if the function is more than a single line (i.e. has a carriage-return).
I read somewhere that this parens/braces distinction might be relaxed but I don't know if that's going to happen any time soon.

Flatten a Map of Option to Map [duplicate]

This question already has answers here:
Scala: Remove none elements from map and flatten
(5 answers)
Closed 7 years ago.
I have a Map[A, Option[B]], what is the optimal way to make a flatten to get a Map[A, B] ?
I know for a list we can use flatten, but this structure is different
Well, they are not the same, so you will need a way to define what happens if a value is None. I assume you want to ignore those keys, if so, you can collect with a partial function:
map.collect {
case (k, Some(v)) => k -> v
}
or use a for-comprehension
for ((k, Some(v)) <- map) yield k -> v
If you don't mind double-iteration:
map.filter(_._2.nonEmpty).mapValues(_.get)
Example:
scala> Map(1 -> Some(1), 2 -> None).filter(_._2.nonEmpty).mapValues(_.get)
res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1)
Or using this implicit:
implicit def flat[K,V](kv: (K, Option[V])) = kv._2.map(kv._1 -> _).toList
Then:
map.flatten.toMap
Or without using (potentially unsafe) implicit:
map flatMap flat
Example:
scala> Map(1 -> Some(1), 2 -> None).flatten.toMap
res2: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1)
scala> def flat[K,V](kv: (K, Option[V])) = kv._2.map(kv._1 -> _).toList
warning: there was one feature warning; re-run with -feature for details
flat: [K, V](kv: (K, Option[V]))List[(K, V)]
scala> Map(1 -> Option(1), 2 -> None).flatMap(flat)
res29: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1)

Understanding Scala -> syntax

I am getting a taste of Scala through the artima "Programming in Scala" book.
While presenting the Map traits, the authors go to some lengths to describe the -> syntax as a method that can be applied to any type to get a tuple.
And indeed:
scala> (2->"two")
res1: (Int, String) = (2,two)
scala> (2,"two")
res2: (Int, String) = (2,two)
scala> (2->"two") == (2, "two")
res3: Boolean = true
But those are not equivalent:
scala> Map(1->"one") + (2->"two")
res4: scala.collection.immutable.Map[Int,String] = Map(1 -> one, 2 -> two)
scala> Map(1->"one") + (2, "two")
<console>:8: error: type mismatch;
found : Int(2)
required: (Int, ?)
Map(1->"one") + (2, "two")
Why is this so, since my first tests seem to show that both "pair" syntaxes build a tuple?
Regards.
They are exactly the same, thanks to this class in Predef (only partly reproduced here):
final class ArrowAssoc[A](val __leftOfArrow: A) extends AnyVal {
#inline def -> [B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y)
}
#inline implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x)
So now the question is when will (a,b) syntax be ambiguous where (a -> b) is not? And the answer is in function calls, especially when they're overloaded:
def f[A](a: A) = a.toString
def f[A,B](a: A, b: B) = a.hashCode + b.hashCode
f(1,2) // Int = 3
f(1 -> 2) // String = (1,2)
f((1, 2)) // String = (1,2)
Map + in particular gets confused because it's overloaded with a multiple-argument version, so you could
Map(1 -> 2) + (3 -> 4, 4 -> 5, 5 -> 6)
and it thus interprets
Map(1 -> 2) + (3, 4)
as trying to add both 3 to the map, and then 4 to the map. Which of course makes no sense, but it doesn't try the other interpretation.
With -> there is no such ambiguity.
However, you can't
Map(1 -> 2) + 3 -> 4
because + and - have the same precedence. Thus it is interpreted as
(Map(1 -> 2) + 3) -> 4
which again fails because you're trying to add 3 in place of a key-value pair.

Why Scala REPL shows tuple type for Map expression?

Scala REPL gives the same type for both expressions - (tuple? -- strange!). Yet ("a" ->1) which is a Map I can add to map and ("a", 1)can not. Why Scala REPL shows tuple type type for Map expression?
scala> :t ("a" -> 1)
(String, Int)
scala> :t ("a",1)
(String, Int)
scala> val m = Map.empty[String, Int]
m: scala.collection.immutable.Map[String,Int] = Map()
scala> m + ("a",1)
<console>:9: error: type mismatch;
found : String("a")
required: (String, ?)
m + ("a",1)
^
scala> m + ("a" ->1)
res19: scala.collection.immutable.Map[String,Int] = Map(a -> 1)
Scala thinks a + (b,c) means you are trying to call the + method with two arguments, which is a real possibility since maps do have a multi-argument addition method so you can do things like
m + (("a" -> 1), ("b" -> 2))
the solution is simple: just add an extra set of parentheses so it's clear that (b,c) is in fact a tuple being passed as a single argument.
m + (("a", 1))
Actually, the reason for this is that Predef: http://www.scala-lang.org/api/current/index.html#scala.Predef$ (which is always in scope in Scala) contains an implicit conversion from Any to ArrowAssoc (the method implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A])
ArrowAssoc contains the method -> which converts it to a tuple.
So basically you are doing any2ArrowAssoc("a").->(1) which returns ("a",1).
From repl:
any2ArrowAssoc("a").->(1)
res1: (java.lang.String, Int) = (a,1)
Furthermore, you can work on immutable hashmaps like this:
val x = HashMap[Int,String](1 -> "One")
x: scala.collection.immutable.HashMap[Int,String] = Map((1,One))
val y = x ++ HashMap[Int,String](2 -> "Two")
y: scala.collection.immutable.Map[Int,String] = Map((1,One), (2,Two))
val z = x + (3 -> "Three")
z: scala.collection.immutable.HashMap[Int,String] = Map((1,One), (3,Three))

Scala: How to create a Map[K,V] from a Set[K] and a function from K to V?

What is the best way to create a Map[K,V] from a Set[K] and function from K to V?
For example, suppose I have
scala> val s = Set(2, 3, 5)
s: scala.collection.immutable.Set[Int] = Set(2, 3, 5)
and
scala> def func(i: Int) = "" + i + i
func: (i: Int)java.lang.String
What is the easiest way of creating a Map[Int, String](2 -> "22", 3 -> "33", 5 -> "55")
You can use foldLeft:
val func2 = (r: Map[Int,String], i: Int) => r + (i -> func(i))
s.foldLeft(Map.empty[Int,String])(func2)
This will perform better than Jesper's solution, because foldLeft constructs the Map in one pass. Jesper's code creates an intermediate data structure first, which then needs to be converted to the final Map.
Update: I wrote a micro benchmark testing the speed of each of the answers:
Jesper (original): 35s 738ms
Jesper (improved): 11s 618ms
dbyrne: 11s 906ms
Rex Kerr: 12s 206ms
Eastsun: 11s 988ms
Looks like they are all pretty much the same as long as you avoid constructing an intermediate data structure.
What about this:
(s map { i => i -> func(i) }).toMap
This maps the elements of s to tuples (i, func(i)) and then converts the resulting collection to a Map.
Note: i -> func(i) is the same as (i, func(i)).
dbyrne suggests creating a view of the set first (see his answer and comments), which prevents an intermediate collection from being made, improving performance:
(s.view map { i => i -> func(i) }).toMap
scala> import collection.breakOut
import collection.breakOut
scala> val set = Set(2,3,5)
set: scala.collection.immutable.Set[Int] = Set(2, 3, 5)
scala> def func(i: Int) = ""+i+i
func: (i: Int)java.lang.String
scala> val map: Map[Int,String] = set.map(i => i -> func(i))(breakOut)
map: Map[Int,String] = Map(2 -> 22, 3 -> 33, 5 -> 55)
scala>
In addition to the existing answers,
Map() ++ set.view.map(i => i -> f(i))
is pretty short and performs as well as the faster answers (fold/breakOut).
(Note the view to prevent creation of a new collection; it does the remapping as it goes.)
The other solutions lack creativity. Here's my own version, though I'd really like to get rid of the _.head map.
s groupBy identity mapValues (_.head) mapValues func
As with all great languages, there's a million ways to do everything.
Here's a strategy that zips the set with itself.
val s = Set(1,2,3,4,5)
Map(s.zip(s.map(_.toString)).toArray : _*)
EDIT: (_.toString) could be replaced with some function that returns something of type V
Without definition of func(i: Int) using "string repeating" operator *:
scala> s map { x => x -> x.toString*2 } toMap
res2: scala.collection.immutable.Map[Int,String] = Map(2 -> 22, 3 -> 33, 5 -> 55)