找到一个像样的替代强制显式类型注释的方法?

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,这正是我要找的。