为什么不是effects
一个Effect[A]
?类型应从排列foo
。
/***
scalaVersion := "2.11.8"
*/
trait Effect[A]
sealed trait ActionResult[+M, +A] {
}
sealed trait ModelUpdated[+M] extends ActionResult[M, Nothing] {
}
sealed trait HasEffect[+M, +A] extends ActionResult[M, A] {
}
sealed trait UpdateSilent
object ActionResult {
case object NoChange extends ActionResult[Nothing, Nothing]
final case class ModelUpdate[M](newModel: M) extends ModelUpdated[M]
final case class ModelUpdateSilent[M](newModel: M) extends ModelUpdated[M] with UpdateSilent
final case class EffectOnly[A](effect: Effect[A]) extends ActionResult[Nothing, A] with HasEffect[Nothing, A]
final case class ModelUpdateEffect[M, A](newModel: M, effect: Effect[A]) extends ModelUpdated[M] with HasEffect[M, A]
final case class ModelUpdateSilentEffect[M, A](newModel: M, effect: Effect[A])
extends ModelUpdated[M] with HasEffect[M, A] with UpdateSilent
def apply[M, A](model: Option[M], effect: Option[Effect[A]]): ActionResult[M, A] = (model, effect) match {
case (Some(m), Some(e)) => ModelUpdateEffect(m, e)
case (Some(m), None) => ModelUpdate(m)
case (None, Some(e)) => EffectOnly(e)
case _ => NoChange
}
}
object Main {
def foo[A, B]: ActionResult[A, B] = ???
def dispatch[A, B] = {
foo[A, B] match {
case ActionResult.NoChange =>
false
case ActionResult.ModelUpdate(newModel) =>
false
case ActionResult.ModelUpdateSilent(newModel) =>
true
case ActionResult.EffectOnly(effects) =>
true
case ActionResult.ModelUpdateEffect(newModel, effects) =>
val e: Effect[A] = effects
false
case ActionResult.ModelUpdateSilentEffect(newModel, effects: Effect[A]) =>
true
}
}
}
我每个人都没有答案,但这是一些想法。首先,我已经简化并阐明了您的代码示例,以最大程度地减少问题的发生:
trait Effect[A]
trait ActionResult[+M, +A]
trait ModelUpdated[+M] extends ActionResult[M, Nothing]
trait HasEffect[+M, +A] extends ActionResult[M, A]
case class ModelUpdateEffect[M, A](newModel: M, effect: Effect[A]) extends ModelUpdated[M] with HasEffect[M, A]
object Main {
def foo[M, A]: ActionResult[M, A] = ???
def dispatch[M, A] = {
foo[M, A] match {
case ModelUpdateEffect(newModel, effect) =>
val e: Effect[A] = effect // does not compile
false
case _ => true
}
}
}
让我们记下该行的错误消息:
type mismatch;
found : Effect[Any]
required: Effect[A]
Note: Any >: A, but trait Effect is invariant in type A.
编译器决定使用effect
type有点奇怪Effect[Any]
。但是让我们看看如果替换此定义会发生什么:
case class ModelUpdateEffect[M, A](newModel: M, effect: Effect[A]) extends ModelUpdated[M] with HasEffect[M, A]
有了这个:
case class ModelUpdateEffect[M, A](newModel: M, effect: Effect[A]) extends HasEffect[M, A]
现在我们得到了另一个错误消息:
type mismatch;
found : Effect[?A1] where type ?A1 <: A (this is a GADT skolem)
required: Effect[A]
Note: ?A1 <: A, but trait Effect is invariant in type A.
在这种情况下,类型确实不匹配。让我们来看一看。从case
声明之外我们知道我们有一个ActionResult[M, A]
。但是由于类型参数的协方差A
,ActionResult[M, A]
很有可能是一个ActionResult[M, B] forSome { type B <: A }
。换句话说,可能有某种类型B
是的子类型A
,并且foo[M, A]
可能返回ActionResult[M, B]
。在这种情况下,effect
将是Effect[B]
,并且由于for的类型参数Effect
是不变的,因此该类型与不兼容Effect[A]
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句