我试图在方法中使用依赖于类型的类型类,如下所示:
@typeclass trait Identifiable[M] {
type K
def identify(id: M): K
}
object Identifiable {
type Aux[M, K0] = Identifiable[M] { type K = K0 }
implicit def identifiableTuple[K1, K2](
implicit
a: Identifiable[K1],
b: Identifiable[K2]
): Identifiable.Aux[(K1, K2), (a.K, b.K)] = new Identifiable[(K1, K2)] {
type K = (a.K, b.K)
override def identify(id: (K1, K2)): K = {
val k1 = a.identify(id._1)
val k2 = b.identify(id._2)
(k1, k2)
}
}但是,当我尝试像下面这样使用它时,隐式参数不会被解析。
def a[K: Identifiable](key:K) = {
case k =>
val keyString: String = the[Identifiable.Aux[K, String]].identify(key)
case (k1,k2) =>
val keyString: (String,String) = the[Identifiable.Aux[K, (String, String)]].identify(key) }发布于 2020-04-05 17:55:32
您要求在类型约束中使用路径依赖类型隐式,但随后调用该类型的隐式,该类型固定在某物上。
为此,编译器必须能够证明可识别的依赖类型等于K,这在当前代码中是无法做到的。
你可以试试:
ev: identifiable.K =:= K
发布于 2020-04-05 18:01:26
模式(k1,k2)应该在无约束模式k之前,否则一切都会转到k,而不是(k1,k2)。
模式匹配主要在运行时工作,类型类/隐式大部分在编译时工作。由于您开始使用类型类(此外,使用带有类型成员的类型类),所以您似乎希望在编译时对类型进行一些计算,即一些计算。
运行时的逻辑分支对应于模式匹配。编译时的逻辑分支对应于一个类型类,并且有几个类型类的定义实例。
尝试使a()成为一个类型类
trait A[K] {
def apply(key: K): Unit
}
object A {
implicit def tupleA[K](implicit identifiable: Identifiable.Aux[K, (String, String)]): A[K] = new A[K] {
override def apply(key: K): Unit = key match {
case (k1, k2) =>
val keyString: (String, String) = identifiable.identify(key)
()
}
}
implicit def defaultA[K](implicit identifiable: Identifiable.Aux[K, String]): A[K] = new A[K] {
override def apply(key: K): Unit = {
val keyString: String = identifiable.identify(key)
()
}
}
}
def a[K](key: K)(implicit aInstance: A[K]) = aInstance(key)您应该编写一些示例,说明您计划如何应用a()。关于什么输入,你期望什么输出。应该编译什么,不应该编译什么?
通常类型参数(如M表示Identifiable[M])类似于输入,类型成员(如K表示Identifiable[M] { type K })类似于类型级计算的输出。因此,对于Identifiable,看起来K类型将被选择为M类型。这是正确的吗?请考虑你的逻辑(什么是输入,什么输出)。在a()中,您似乎开始根据K的类型来做一些事情。
发布于 2020-04-05 18:17:13
但你为什么要指望他们能匹配呢?在case k =>分支中,存在类型为Identifiable[K]的隐式,但没有理由期望它是您试图用the请求的Identifiable[K] { type K = String }。或者是另一个分支中的Identifiable[K] { type K = (String, String) }。(请注意,K有两个不同的含义,这可能有点让人困惑。)
来自注释case类K1(值: String);case类K2(值: String)我期望: a(K1) =>字符串和((K1,K2)) => ( String,String)
最合理的选择接近你想要的似乎是简单的
def a[A](key:A)(implicit ev: Identifiable[A]): ev.K = ev.identify(key)https://stackoverflow.com/questions/61046802
复制相似问题