HOMap实现示例

时间:2014-03-20 22:05:48

标签: scala collections higher-kinded-types

我正在看this video by Daniel Spiewak,并尝试从中实施有关高级种类的样本。这就是我得到的:

/* 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)

不幸的是启动这个我得到了类型不匹配错误:

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

我的问题:

  1. 我该如何解决这个问题?我完全理解我只需要传递正确的类型,但我在Scala中使用这种东西的经验很差,我无法弄清楚这一点。
  2. 为什么会这样?我的意思是操作tuples: _*可能被广泛用于传递给Map,但它以某种方式提供了一些奇怪的类型 - Main.$anon.HOMap.Pair[K,V]*而不是它应该给予的内容。
  3. 为什么这个例子不再起作用?也许最近对Scala语言的一些更改改变了一些语法?
  4. 感谢您的回答!

1 个答案:

答案 0 :(得分:2)

类型varince条件中的问题。在def apply[K[_], V[_]]行中,您需要保证容器K[_] & V[_]可以投放到K[Any] & V[Any]

只需将类型covarince约束(+)添加到K& V容器:

object HOMap {
  def apply[K[+_], V[+_]](tuples: (Pair[K[A], V[A]] forSome { type A })*) =
    new HOMap[K, V](Map(tuples: _*))
}