找到强制性显式类型注释的替代方法?

时间:2019-04-11 23:56:29

标签: scala generics types 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]

当我尝试使用此apply方法实例化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]] ,而不是设置[MidState [S]] ,它是应用方法所必需的。尽管将(State(“ C”):: Nil).toSet 直接插入到apply方法中,还有什么更好的解决方案可以避免这种显式类型注释?

2 个答案:

答案 0 :(得分:2)

您可以做的第一件事是消除所有:: 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"))

答案 1 :(得分: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 ,这正是我所要的。