模式匹配会丢失类型界限吗?

反应堆僧侣

为什么不是effects一个Effect[A]类型应从排列foo

http://scastie.org/20029

/***
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.

编译器决定使用effecttype有点奇怪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]但是由于类型参数的协方差AActionResult[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] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

模式匹配会丢失类型界限吗?

来自分类Dev

在恢复模式下会丢失数据吗?

来自分类Dev

在恢复模式下我会丢失数据吗?

来自分类Dev

输入类型=“文件”会自动丢失文件吗?

来自分类Dev

可以在模式匹配中引用类型变量吗?

来自分类Dev

F#的衍生类型上的模式匹配是惯用的吗?

来自分类Dev

HTTP请求会丢失吗?

来自分类Dev

如果以只读模式读取文件时断电,会丢失该文件的数据吗?

来自分类Dev

Haskell:类型与模式匹配

来自分类Dev

类型的模式匹配

来自分类Dev

do-notation/enumFromTo 中的模式匹配会减慢 Haskell 代码的速度吗?

来自分类Dev

如果升级,会丢失数据吗?

来自分类Dev

我会丢失内存分配吗?

来自分类Dev

如果升级,会丢失数据吗?

来自分类Dev

调用onUpgrade时数据会丢失吗

来自分类Dev

类型类之间的模式匹配

来自分类Dev

Haskell中类型匹配的模式

来自分类Dev

与列表类型匹配的FSharp模式

来自分类Dev

Haskell中类型匹配的模式

来自分类Dev

与列表类型匹配的FSharp模式

来自分类Dev

定义涉及模式匹配的类型

来自分类Dev

泛型类型的模式匹配

来自分类Dev

Scala 模式与元组类型匹配

来自分类Dev

使用参数化查询会导致数据类型不匹配。有任何想法吗?

来自分类Dev

npm ls匹配模式吗?

来自分类Dev

头尾模式匹配参数的匹配类型

来自分类Dev

类型不匹配且模式匹配

来自分类Dev

头尾模式匹配参数的匹配类型

来自分类Dev

您可以在Haskell的类型级别上进行模式匹配吗?