从必须实现类型类的方法返回值
Returning a value from a method which must implement a typeclass
我正在尝试使用一个方法 return 一个必须实现类型类的值,我认为它更普遍地向我强调了我如何不理解 Scala 的通用参数解析过程。我有这样的情况:
trait IsContainer[A, T] {
def getOtherContainer[O](implicit tc2: IsUnit[O]): O
}
trait IsUnit[A] { }
implicit val anIntIsUnit = new IsUnit[Int] { }
implicit def aListIsContainer[T] = new IsContainer[List[T], T] {
def getOtherContainer[Int] = 3
}
这引发了编译错误:Missing implementation for: def getOtherContainer
。我对这里应该发生什么的不知情的猜测是 Scala 看到我已经传递了通用参数 O
,并考虑如果 O
类型的所有实例都一致则实现的方法。所以在这种情况下(因为我已经明确地告诉它 O
= Int
,它会检查范围内是否存在 IsUnit[Int]
的实例,并且该方法的输出类型是输入 O
。如果这是正确的(我不是说它是!)那么为什么它不起作用?
更一般地说,如果我跳过 [O]
通用参数并让它猜测 - 所以我只是用 getOtherContainer = 3
实现了该方法 - 我是否也应该期望它起作用?为了推断 O
应该是什么,它是否扫描该行并查看 O
是否已在提到的三个地方中的任何一个具体填写,并据此推断?
谢谢!
主要问题是这个定义:
def getOtherContainer[Int] = 3
在这个定义中,Int
是一个类型参数,而不是类型Int
。完全一样
def getOtherContainer[T] = 3
所以你没有“明确地告诉它 O
= Int
”,你只是使用 Int
作为类型参数的名称而不是 O
。由于这与特征中所需的签名不匹配,因此没有有效的 getOtherContainer
实现,您会收到错误消息。
正确的是
implicit def aListIsContainer[T] = new IsContainer[List[T], T] {
override def getOtherContainer[O](implicit tc2: IsUnit[O]): O = ???
}
你喜欢的类型class
trait IsContainer[A, T] {
def getOtherContainer[O](implicit tc2: IsUnit[O]): O
}
意味着如果 A
、T
类型的元组有一个 class 类型的实例,那么您知道如何做 getOtherContainer
对于任何 类型 O
具有类型 class IsUnit
.
的实例
当您试图在实例定义中删除 (implicit tc2: IsUnit[O])
或 [O]
时,您实际上是在试图违反 class.[=28= 类型的契约]
如果你想在一个实例中特化O
(例如O := Int
)那么你应该将类型参数O
移动到类型class级别
trait IsContainer[A, T, O] {
def getOtherContainer(implicit tc2: IsUnit[O]): O
}
或
abstract class IsContainer[A, T, O](implicit tc2: IsUnit[O]) {
def getOtherContainer: O
}
或
trait IsContainer[A, T] {
type O
def getOtherContainer(implicit tc2: IsUnit[O]): O
}
然后你可以定义一个实例
implicit def aListIsContainer[T] = new IsContainer[List[T], T, Int] {
override def getOtherContainer(implicit tc2: IsUnit[Int]): Int = 3
}
或
implicit def aListIsContainer[T] = new IsContainer[List[T], T, Int] {
override def getOtherContainer: Int = 3
}
或
implicit def aListIsContainer[T] = new IsContainer[List[T], T] {
override type O = Int
override def getOtherContainer(implicit tc2: IsUnit[O]): O = 3
}
相应地。
我正在尝试使用一个方法 return 一个必须实现类型类的值,我认为它更普遍地向我强调了我如何不理解 Scala 的通用参数解析过程。我有这样的情况:
trait IsContainer[A, T] {
def getOtherContainer[O](implicit tc2: IsUnit[O]): O
}
trait IsUnit[A] { }
implicit val anIntIsUnit = new IsUnit[Int] { }
implicit def aListIsContainer[T] = new IsContainer[List[T], T] {
def getOtherContainer[Int] = 3
}
这引发了编译错误:Missing implementation for: def getOtherContainer
。我对这里应该发生什么的不知情的猜测是 Scala 看到我已经传递了通用参数 O
,并考虑如果 O
类型的所有实例都一致则实现的方法。所以在这种情况下(因为我已经明确地告诉它 O
= Int
,它会检查范围内是否存在 IsUnit[Int]
的实例,并且该方法的输出类型是输入 O
。如果这是正确的(我不是说它是!)那么为什么它不起作用?
更一般地说,如果我跳过 [O]
通用参数并让它猜测 - 所以我只是用 getOtherContainer = 3
实现了该方法 - 我是否也应该期望它起作用?为了推断 O
应该是什么,它是否扫描该行并查看 O
是否已在提到的三个地方中的任何一个具体填写,并据此推断?
谢谢!
主要问题是这个定义:
def getOtherContainer[Int] = 3
在这个定义中,Int
是一个类型参数,而不是类型Int
。完全一样
def getOtherContainer[T] = 3
所以你没有“明确地告诉它 O
= Int
”,你只是使用 Int
作为类型参数的名称而不是 O
。由于这与特征中所需的签名不匹配,因此没有有效的 getOtherContainer
实现,您会收到错误消息。
正确的是
implicit def aListIsContainer[T] = new IsContainer[List[T], T] {
override def getOtherContainer[O](implicit tc2: IsUnit[O]): O = ???
}
你喜欢的类型class
trait IsContainer[A, T] {
def getOtherContainer[O](implicit tc2: IsUnit[O]): O
}
意味着如果 A
、T
类型的元组有一个 class 类型的实例,那么您知道如何做 getOtherContainer
对于任何 类型 O
具有类型 class IsUnit
.
当您试图在实例定义中删除 (implicit tc2: IsUnit[O])
或 [O]
时,您实际上是在试图违反 class.[=28= 类型的契约]
如果你想在一个实例中特化O
(例如O := Int
)那么你应该将类型参数O
移动到类型class级别
trait IsContainer[A, T, O] {
def getOtherContainer(implicit tc2: IsUnit[O]): O
}
或
abstract class IsContainer[A, T, O](implicit tc2: IsUnit[O]) {
def getOtherContainer: O
}
或
trait IsContainer[A, T] {
type O
def getOtherContainer(implicit tc2: IsUnit[O]): O
}
然后你可以定义一个实例
implicit def aListIsContainer[T] = new IsContainer[List[T], T, Int] {
override def getOtherContainer(implicit tc2: IsUnit[Int]): Int = 3
}
或
implicit def aListIsContainer[T] = new IsContainer[List[T], T, Int] {
override def getOtherContainer: Int = 3
}
或
implicit def aListIsContainer[T] = new IsContainer[List[T], T] {
override type O = Int
override def getOtherContainer(implicit tc2: IsUnit[O]): O = 3
}
相应地。