gpt4 book ai didi

scala - 使用高级类型的通用约束映射?

转载 作者:行者123 更新时间:2023-12-01 11:42:29 24 4
gpt4 key购买 nike

我正在尝试实现一个映射类 Loader 的可散列实例的结果缓存( Resolver[T] 类)至 Result实例,其中 T类型为 Result .当然,用户可以专门化 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 语言比较陌生,我的问题是:是否有可能通过使用 Scala 提供的高级类型功能来实现这种隐式转换?我看了一下谈话 'High Wizardry in the Land of Scala'演讲者 Daniel Spiewak 介绍了一个高阶 HOMap这做了类似的事情,但我仍然不太明白如何根据我的情况调整他的解决方案。

最佳答案

首先,你不需要这里的所有存在。在某些情况下,它们只是过于冗长— K forSome { type K <: Resolver[_] }例如,与 K <: Resolver[_] 完全相同.在其他情况下,它们会引入似乎是无意的行为。例如:

class FooResult extends Result { def computed = true }
class BarResult extends Result { def computed = true }

object Foo extends Resolver[FooResult] { def result() = new BarResult }

这编译得很好,因为 Tresult 的返回类型中隐藏类的类型参数 T .

接下来,您是否考虑过这里的惰性值?他们会为你处理这种缓存——你只需定义 resultlazy val result = ...在您的 Resolver实现并且结果将被计算一次(当它第一次需要时)。

如果您决定需要手动处理此缓存,则在这种情况下,您可以证明使用强制转换来欺负编译器是合理的。例如,给定以下设置:
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]

}

我们知道这些类型会起作用,因为只有一种方法可以让配对进入 map 。

更新:我的 Loader这里的解决方案与 Sergey 的解决方案基本相同(请注意,锁定 map 是个好主意,并且您不需要在对 result 的调用周围加上括号,因为 getOrElseUpdate 的第二个参数是按名称)。无论如何,我要留下我的答案,因为前半部分是重要的部分。

关于scala - 使用高级类型的通用约束映射?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18289146/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com