如何避免Scala中类型绑定的重复 [英] How to avoid duplication of type bound in Scala
问题描述
我有一个带有受约束的类型参数的类.
I have a class with a constrained type parameter.
我尝试使用identity
,但是返回类型不精确.
I've tried with identity
but the return type is not precise.
在方法identityTP
中,我需要再次指定约束条件
And in the method identityTP
, I need to specify again the constraint
如何避免使用适用于此类型的方法来重复此约束?
How to avoid to duplicate this constraint with methods that work on this type ?
这里是一个例子:
sealed trait Location
case object Single extends Location
case object Multi extends Location
final case class Log[L <: Location](l: L)
def identity(log: Log[_]): Log[_] = log
def identityTP[L<: Location](log: Log[L]): Log[L] = log
推荐答案
实际上这不是重复项. L
in
Actually this is not a duplication. L
in
final case class Log[L <: Location](l: L)
和L
in
def identityTP[L <: Location](log: Log[L]): Log[L] = log
是两个完全不同的类型参数.如果您使用其他标识符,可能会更清楚
are two completely different type parameters. This could be more clear if you used different identifiers
final case class Log[L <: Location](l: L)
def identityTP[L1 <: Location](log: Log[L1]): Log[L1] = log
一个类型参数的上限不会与其他类型参数的上限重复.
An upper bound for one type parameter doesn't duplicate an upper bound for other type parameter.
这也不是重复的,因为实际上上限可以不同
Also this is not a duplication because actually upper bounds can be different
sealed trait SubLocation extends Location
final case class Log[L <: Location](l: L)
def identityTP[L1 <: SubLocation](log: Log[L1]): Log[L1] = log
如果不想创建第二个类型参数,可以将identityTP
嵌套到Log
中(使其成为Log
的方法)
If you don't want to create the second type parameter you can make identityTP
nested into Log
(making it Log
's method)
final case class Log[L <: Location](l: L) {
def identityTP: Log[L] = this
}
如果您将L
设置为类型成员而不是类型参数,有时会有所帮助
Sometimes it can help if you make L
a type member rather than type parameter
trait Log {
type L <: Location
val l: L
}
object Log {
// def apply[_L <: Location](_l: _L): Log { type L = _L} = new Log {
// override type L = _L
// override val l: L = _l
// }
def apply[_L <: Location](_l: _L): Log = new Log {
override type L = _L
override val l: L = _l
}
}
// def identityTP(log: Log): Log = log
def identityTP(log: Log): Log { type L = log.L } = log
请注意,尽管我们必须在apply
中重复上界,但在identityTP
中没有.
Notice that although we have to repeat upper bound in apply
but we don't have in identityTP
.
通常在必要时重复上限不是什么大事
Normally it's not a big deal to repeat upper bound when necessary
class MyClass[A <: A1]
def foo[A <: A1](mc: MyClass[A]) = ???
def bar[A <: A1](mc: MyClass[A]) = ???
麻烦的时候
class MyClass[A <: A1, B <: B1, C <: C1]
def foo[A <: A1, B <: B1, C <: C1](mc: MyClass[A, B, C]) = ???
def bar[A <: A1, B <: B1, C <: C1](mc: MyClass[A, B, C]) = ???
您应该重新设计抽象.例如
you should redesign your abstractions. For example
trait Tuple {
type A <: A1
type B <: B1
type C <: C1
}
class MyClass[T <: Tuple]
def foo[T <: Tuple](mc: MyClass[T]) = {
//T#A, T#B, T#C instead of A, B, C
???
}
或
class MyClass[T <: Tuple](val t: T)
//class MyClass(val t: Tuple)
def foo[T <: Tuple](mc: MyClass[T]) = {
//def foo(mc: MyClass) = {
import mc.t
//t.A, t.B, t.C instead of A, B, C
???
}
有时您还可以使用类型约束替换类型边界
Also sometimes you can play with replacing type bounds with type constraints
final case class Log[L](l: L)(implicit ev: L <:< Location)
def identityTP[L](log: Log[L])(implicit ev: L <:< Location): Log[L] = log
尽管这不会删除重复项,但是也有一些方法可以与隐式参数(类型类)之间的重复项作斗争.参见如何包装具有隐式使用Scala中的另一种方法?
Although this doesn't remove repetitions but there are ways to fight against repetitions among implicit parameters as well (type classes). See How to wrap a method having implicits with another method in Scala?
这篇关于如何避免Scala中类型绑定的重复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!