找到一个像样的替代强制显式类型注释的方法?
Find a decent alternative to forced explicit type annotation?
在测试我最近创建的一些代码时,我发现有些段落在没有显式类型注释的情况下无法编译。我试图在以下代码片段中尽量减少问题:
case class Base[E,S](al:Set[E],sts:Set[MidState[S]],ss:MidState[S],
d:Map[(MidState[S],E),MidState[S]],aS:Set[MidState[S]])
case class Edge[E,S](state_1: MidState[S],l:E ,state_2: MidState[S])
sealed trait MidState[S] extends BaseState[S]
sealed case class State[S](l:S)
extends MidState[S]
case object FailureState extends MidState[Nothing]
Base 有一个伴生对象,其 apply 方法定义如下:
object Base {
def apply [E,S](edges:Set[Edge[E,S]],ss:MidState[S],
aS:Set[MidState[S]],partialMode:Boolean): Base[E,S]
当我尝试使用此应用方法实例化 Base 时,我无法绕过 aS 的显式类型注释:
val aS : Set[MidState[String]] = (State("C") :: Nil).toSet
val base = Base(edges,State("A"),aS,partialMode = true)
如果我删除 aS 的显式类型注释,aS 的类型为 Set[State[S] ] 而不是 Set[MidState[S]] ,它需要用于应用方法。尽管将 (State("C") :: Nil).toSet 直接插入 apply 方法,但是否有更好的解决方案来避免这种显式类型注释?
您可以做的第一件事是删除所有 :: Nil
和 .toSet
以及 : ...
噪声:
val aS = Set[MidState[String]](State("C"))
这实际上很常见:例如,它经常作为第一个参数出现在 fold
中,必须显式地写成 Set[Int]()
或 Set.empty[Int]
才能得到类型正确。
如果这仍然太嘈杂,只需将适当的工厂方法添加到 MidState
:
object MidState {
def apply[S](s: S): MidState[S] = State(s)
}
然后立即调用构造正确类型对象的工厂方法:
val bS = Set(MidState("C"))
Andrey Tyukin 通过向 MidState class 添加工厂方法引入了一个解决方案,效果很好。但是,我通过向 apply-method 添加类型限制解决了这个问题,因此签名更改为:
object Base {
def apply [E,S](edges:Set[Edge[E,S]],ss:MidState[S],
aS:Set[MidState[S]],partialMode:Boolean): Base[E,S]
至:
object Base {
def apply [E,S](edges:Set[Edge[E,S]],ss:MidState[S],
aS:Set[_ <: MidState[S]],partialMode:Boolean): Base[E,S]
现在我们可以传递任何包含 MidState 子类型元素的集合 aS,这正是我要找的。
在测试我最近创建的一些代码时,我发现有些段落在没有显式类型注释的情况下无法编译。我试图在以下代码片段中尽量减少问题:
case class Base[E,S](al:Set[E],sts:Set[MidState[S]],ss:MidState[S],
d:Map[(MidState[S],E),MidState[S]],aS:Set[MidState[S]])
case class Edge[E,S](state_1: MidState[S],l:E ,state_2: MidState[S])
sealed trait MidState[S] extends BaseState[S]
sealed case class State[S](l:S)
extends MidState[S]
case object FailureState extends MidState[Nothing]
Base 有一个伴生对象,其 apply 方法定义如下:
object Base {
def apply [E,S](edges:Set[Edge[E,S]],ss:MidState[S],
aS:Set[MidState[S]],partialMode:Boolean): Base[E,S]
当我尝试使用此应用方法实例化 Base 时,我无法绕过 aS 的显式类型注释:
val aS : Set[MidState[String]] = (State("C") :: Nil).toSet
val base = Base(edges,State("A"),aS,partialMode = true)
如果我删除 aS 的显式类型注释,aS 的类型为 Set[State[S] ] 而不是 Set[MidState[S]] ,它需要用于应用方法。尽管将 (State("C") :: Nil).toSet 直接插入 apply 方法,但是否有更好的解决方案来避免这种显式类型注释?
您可以做的第一件事是删除所有 :: Nil
和 .toSet
以及 : ...
噪声:
val aS = Set[MidState[String]](State("C"))
这实际上很常见:例如,它经常作为第一个参数出现在 fold
中,必须显式地写成 Set[Int]()
或 Set.empty[Int]
才能得到类型正确。
如果这仍然太嘈杂,只需将适当的工厂方法添加到 MidState
:
object MidState {
def apply[S](s: S): MidState[S] = State(s)
}
然后立即调用构造正确类型对象的工厂方法:
val bS = Set(MidState("C"))
Andrey Tyukin 通过向 MidState class 添加工厂方法引入了一个解决方案,效果很好。但是,我通过向 apply-method 添加类型限制解决了这个问题,因此签名更改为:
object Base {
def apply [E,S](edges:Set[Edge[E,S]],ss:MidState[S],
aS:Set[MidState[S]],partialMode:Boolean): Base[E,S]
至:
object Base {
def apply [E,S](edges:Set[Edge[E,S]],ss:MidState[S],
aS:Set[_ <: MidState[S]],partialMode:Boolean): Base[E,S]
现在我们可以传递任何包含 MidState 子类型元素的集合 aS,这正是我要找的。