Вопрос

I was watching this video by Daniel Spiewak and tried to implement sample about Higher Kinds from it. Here's what I get:

/* bad style */

val map: Map[Option[Any], List[Any]] = Map (
  Some("foo") -> List("foo", "bar", "baz"),
  Some(42) -> List(1, 1, 2, 3, 5, 8),
  Some(true) -> List(true, false, true, false)
)

val xs: List[String] =
  map(Some("foo")).asInstanceOf[List[String]]  // ugly cast                                                                                                                                       
val ys: List[Int] =
  map(Some(42)).asInstanceOf[List[Int]]  // another one                                                                                                                                           

println(xs)
println(ys)

/* higher kinds usage */

// HOMAP :: ((* => *) x (* => *)) =>     *                                                                                                                                                            
class HOMap[K[_], V[_]](delegate: Map[K[Any], V[Any]]) {
  def apply[A](key: K[A]): V[A] =
    delegate(key.asInstanceOf[K[Any]]).asInstanceOf[V[A]]
}

object HOMap {
  type Pair[K[_], V[_]] = (K[A], V[A]) forSome { type A }

  def apply[K[_], V[_]](tuples: Pair[K, V]*) =
    new HOMap[K, V](Map(tuples: _*))
}

val map_b: HOMap[Option, List] = HOMap[Option, List](
  Some("foo") -> List("foo", "bar", "baz"),
  Some(42) -> List(1, 1, 2, 3, 5, 8),
  Some(true) -> List(true, false, true, false)
)

val xs_b: List[String] = map_b(Some("foo"))

val ys_b: List[Int] = map_b(Some(42))

println(xs_b)
println(ys_b)

Unfortunately launching this I get the type mismatch error:

username@host:~/workspace/scala/samples$ scala higher_kinds.scala
/home/username/workspace/scala/samples/higher_kinds.scala:30: error: type mismatch;
 found   : Main.$anon.HOMap.Pair[K,V]*
 required: Seq[(K[Any], V[Any])]
     new HOMap[K, V](Map(tuples: _*))
                    ^
one error found

My questions:

  1. How can I fix this? I fully understand that I just need to pass in the right type, but my experience with this kind of stuff in Scala is poor and I can't figure out this.
  2. Why this happens? I mean the operation tuples: _* is probably used widely for passing to Map, but it somehow gives some strange type - Main.$anon.HOMap.Pair[K,V]* and not what it's supposed to give.
  3. Why that example is no longer work? Maybe some recent changes to Scala language changed some syntax?

Thanks for answers!

Это было полезно?

Решение

Problem in type varince conditions. In line def apply[K[_], V[_]] you need guaranty that containers K[_] & V[_] can be cast to K[Any] & V[Any]

Just add type covarince constraint (+) to K & V containers:

object HOMap {
  def apply[K[+_], V[+_]](tuples: (Pair[K[A], V[A]] forSome { type A })*) =
    new HOMap[K, V](Map(tuples: _*))
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top