为什么自我注释的特征不能分配给自我类型?

Rea*_*ren 4 scala scala-3

trait Base

trait Plugin { base: Base =>
    def asBase: Base & Plugin = this
}

class Mix extends Base, Plugin

val plug: Plugin = new Mix
val baseA: Base= plug.asBase
val baseB: Base = plug // snorts with "Found: Plugin. Required: Base
Run Code Online (Sandbox Code Playgroud)

为什么?如果我是正确的,则遵守里氏替换原则,因为 的所有实例Plugin都是具体类型,该类型是包含 的子类型的混合Base。因此,Base可以用type的对象替换type的对象Plugin,而不影响程序的正确性。

Dmy*_*tin 5

里氏原理说

\n

https://en.wikipedia.org/wiki/Liskov_substitution_principle

\n
\n

子类型要求:设是关于类型 的\xcf\x95(x)对象的可证明属性。对于类型为 的子类型的对象,则应该如此。xT\xcf\x95(y)ySST

\n

子类型中的先决条件无法得到强化。

\n

子类型中的后置条件不能被削弱。

\n

不变量必须保留在子类型中。

\n
\n

里氏原则是关于子类型的。里氏原理现在不适用,因为Plugin它不是Base

\n
implicitly[Plugin <:< Base] // doesn\'t compile\n
Run Code Online (Sandbox Code Playgroud)\n

(比/sf/answers/5303386441/<:<弱,但这对我们来说没问题;如果是ie的子类型,那么更会是)。<: PluginBasePlugin <: Baseimplicitly[Plugin <:< Base]

\n

trait Plugin { base: Base => }我猜您将trait Plugin extends Base(继承)与子类型混淆了

\n

Scala(和 Java)中的类和类型有什么区别?

\n

类型和类别有什么区别?

\n

https://typelevel.org/blog/2017/02/13/more-types-than-classes.html

\n

如何区分参数类型?

\n

Scala 3 中的细化类型和匿名子类有什么区别?

\n

trait Plugin extends Base意味着它Plugin是 的子类Base。特别是,这意味着Plugin是 的子类型Base,因此 的所有子类型Plugin都是 的子类型Base。\n但是trait Plugin { base: Base => }意味着 的所有子Plugin都必须是 的子类Base。这并不意味着 的所有子类型都必须Plugin是 的子类型Base(而且,这并不意味着Plugin是 的子类型Base)。事实上,声明类型很容易

\n
type SubPlugin <: Plugin\n
Run Code Online (Sandbox Code Playgroud)\n

这不是 的子类型Base

\n
implicitly[SubPlugin <:< Base] // doesn\'t compile\n
Run Code Online (Sandbox Code Playgroud)\n
\n

的所有实例Plugin都是具体类型,该类型是包含 的子类型的混合Base

\n
\n

即使 的所有(OOP 实例)Plugin都是 this 的值(实例),Base这并不构成Plugin的子类型Base,并且这并不意味着类型的所有术语Plugin都是类型 的术语Base。例如,术语xinval x: Plugin = ???不是类型 的术语Base

\n

您不应该将类型(仅)视为该类型的所有值的集合(特别是这在类型级编程中变得很重要,其中值根本不那么有趣)。\n集合可以是一个模型(在逻辑中)意义: https: //en.wikipedia.org/wiki/Model_theory)用于类型。但集合和类型不同

\n

https://cs.stackexchange.com/questions/91330/what-exactly-is-the-semantic-difference- Between-set-and-type

\n

https://math.stackexchange.com/questions/489369/difference- Between-a-type-and-a-set

\n

https://planetmath.org/11typetheoryversussettheory

\n

例如,如果我们定义两个抽象类型

\n
type A\n\ntype B\n
Run Code Online (Sandbox Code Playgroud)\n

那么就没有这些类型的值。因此,这些集合在集合论意义上是相等的(空集)。但这些类型是不同的。在同伦类型理论(HoTT,https://en.wikipedia.org/wiki/Homotopy_type_theory)中1 = 2, 和1 = 3是两种没有任何值的类型,但却是两种不同的类型。

\n
\n

因此,Base可以用type的对象替换type的对象Plugin,而不影响程序的正确性。

\n
\n

总有一些程序在运行时不会失败,但在编译时会被拒绝。例如,if true then 1 else "a"运行时不会失败,但可以被没有子类型的语言拒绝,例如 Haskell(但不会被 Scala 拒绝,它认为这是Any)。Scala 会拒绝,val x: Int = if (true) 1 else "a"尽管这在运行时也不会失败。足够丰富的类型系统不可能同时健全和完整。通常,健全性优于完整性

\n

什么是健全的编程语言?

\n

https://math.stackexchange.com/questions/105575/what-is-the-difference- Between-completeness-and-soundness-in-first-order-logic

\n

您可能会问为什么不总是trait Plugin { base: Base => }与 含义相同trait Plugin extends Base。嗯,这是 Scala 类型系统创建者的设计决定。特别是,如果这是相同的,那么两个不同的特征trait A {this: B =>}trait B {this: A =>}具有相同的类型。

\n

同样在 中trait Plugin extends BaseBase必须是一个类/特征。但在 中trait Plugin { base: Base => }Base可以是一种类型。

\n

为什么 scala self 类型不是其要求的子类型

\n

自我类型和特质子类有什么区别?

\n

Trait 继承和 self 类型注释之间的区别

\n

更重要的是 Scala 惯用语:特质 TraitA 扩展 TraitB 或特质 TraitA { self: TraitB => }

\n


归档时间:

查看次数:

76 次

最近记录:

2 年,7 月 前