Scala 使用更高级类型的泛型约束映射?

Scala 使用更高级类型的泛型约束映射?,scala,generics,constraints,higher-kinded-types,Scala,Generics,Constraints,Higher Kinded Types,我正在尝试实现一个结果缓存(Loaderclass),它将类Resolver[T]的哈希实例映射到result实例,其中T的类型为result。当然,用户可以专门化结果类,提供特定于应用程序的额外方法。要点是,使用Loader.get方法,用户还必须指定结果类型: val s = Loader.get(new SpecializedResolver()).asInstanceOf[SpecializedResult] 我想要的是避免强制转换并使其隐式化,因此代码应该如下所示:

我正在尝试实现一个结果缓存(
Loader
class),它将类
Resolver[T]
的哈希实例映射到
result
实例,其中
T
的类型为
result
。当然,用户可以专门化
结果
类,提供特定于应用程序的额外方法。要点是,使用
Loader.get
方法,用户还必须指定结果类型:

    val s = Loader.get(new SpecializedResolver()).asInstanceOf[SpecializedResult]
我想要的是避免强制转换并使其隐式化,因此代码应该如下所示:

    val implicitS = Loader.get(new SpecializedResolver())
我目前掌握的代码如下:

import scala.language.existentials

abstract class Result {
  def computed: Boolean
}

abstract class Resolver[T <: Result] {
    def result(): T forSome {type T <: Result}
}

class SpecializedResult extends Result {
  def computed = true
  def special() = 42
}

class SpecializedResolver extends Resolver[SpecializedResult] {
  def result = new SpecializedResult
}

object Loader {
  val cache = collection.mutable.Map[K forSome {type K <: Resolver[_]}, V forSome {type V <: Result}]()

  def get[K <: Resolver[_]](k: K): V forSome {type V <: Result} = {
    cache.getOrElseUpdate(k, { k.result } )
  }
}

object Runner {
  def main(args: Array[String]) {
    val s = Loader.get(new SpecializedResolver()).asInstanceOf[SpecializedResult]
    println("Value is: %d".format(s.special))

    val implicitS = Loader.get(new SpecializedResolver())
    // test.scala:34: error: value special is not a member of Result
    println("Value is: %d".format(implicitS.special))
  }
}
导入scala.language.existentis
抽象类结果{
def计算:布尔值
}

抽象类解析器[T在您的情况下,您可以使用简单的解决方案(仅更改代码):


abstract class Resolver[T首先,这里不需要所有的存在主义。在某些情况下,它们只是过于冗长{type K我想你想要的是无形状的编码这和我想发布的答案完全一样,如果我有更多的时间和更好的英语:)不要删除它!谢谢你的答案。关于使用惰性变量的问题,我知道这个特性,但重点是结果实例由不同类别在不同的上下文中共享这就是为什么我需要一个特定的缓存解决方案。关于存在主义,你是对的,我滥用它们没有具体的原因。所以感谢你在文章前半部分的解释。非常感谢:)
abstract class Resolver[T <: Result] {
    def result(): T
}
object Loader {
  val cache = collection.mutable.Map[Resolver[_], Any] ()

  def get[K <: Result](k: Resolver[K]): K = {
    cache.getOrElseUpdate(k, { k.result } ).asInstanceOf[K]
  }
}
class FooResult extends Result { def computed = true }
class BarResult extends Result { def computed = true }

object Foo extends Resolver[FooResult] { def result() = new BarResult }
trait Result { def computed: Boolean }
trait Resolver[T <: Result] { def result(): T }
object Loader {
  private[this] val cache = collection.mutable.Map.empty[Resolver[_], Result]

  def get[V <: Result](k: Resolver[V]): V =
    cache.getOrElseUpdate(k, k.result()).asInstanceOf[V]

}