0

在测试我最近创建的一些代码时,我发现有些段落没有显式类型注释就无法编译。我试图在以下代码片段中最小化问题:

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 有一个伴随对象,其应用方法定义如下:

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]],它需要用于 apply 方法。尽管将(State("C") :: Nil).toSet直接插入到 apply 方法中,是否有更好的解决方案来避免这种显式类型注释?

4

2 回答 2

3

您可以做的第一件事是删除所有的:: Nil.toSet: ...噪音:

val aS = Set[MidState[String]](State("C"))

这实际上很常见:例如,它经常作为folds 中的第一个参数出现,其中必须显式编写Set[Int]()Set.empty[Int]为了使类型正确。

如果这仍然太吵,只需将适当的工厂方法添加到MidState

object MidState {
  def apply[S](s: S): MidState[S] = State(s)
}

然后立即调用构造正确类型对象的工厂方法:

val bS = Set(MidState("C"))
于 2019-04-12T02:17:29.857 回答
0

Andrey Tyukin 通过将工厂方法添加到运行良好的 MidState 类引入了一个解决方案。但是,我通过向 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子类型的元素的 Set aS,这正是我想要的。

于 2019-04-13T12:17:16.997 回答