【问题标题】:Confusion about type refinement syntax关于类型细化语法的困惑
【发布时间】:2021-01-06 02:15:36
【问题描述】:

在类型级别上,我偶然发现了以下内容:

sealed abstract class StSource[A] {
  type S
  def init: S            // create the initial state
  def emit(s: S): (A, S) // emit a value, and update state
}

object StSource {
  type Aux[A, S0] = StSource[A] {type S = S0}

  def apply[A, S0](i: S0)(f: S0 => (A, S0)): Aux[A, S0] =
    new StSource[A] {
      type S = S0
      def init = i
      def emit(s: S0) = f(s)
    }
}

让我感兴趣的是type Aux[A, S0] = StSource[A] {type S = S0}

特别是{type S = S0}StSource[A] {type S = S0}

我真的不知道如何阅读这个,就像解释这里所涉及的结构一样。

StSource[A] {type S = S0} 是什么?是不是一种结构类型(部分看起来很像)

当定义像 trait 或类这样的类型时,类的主体是由类本身表示的类型构造函数的一部分吗?里面的方法怎么了?

真的很困惑。有人可以解构吗?

【问题讨论】:

    标签: scala types structural-typing refinement-type


    【解决方案1】:

    StSource[A] {type S = S0} 是一种精炼类型。 {type S = S0} 是一种类型细化。

    从一方面来看,StSource[A] {type S = S0}StSource[A] 的子类型。

    另一方面,StSource[A] 也是相对于StSource[A] {type S = S0} 的存在类型,即StSource[A]StSource.Aux[A, _](又名StSource.Aux[A, X] forSome {type X})。

    def test[A, S] = {
      implicitly[StSource.Aux[A, S] <:< StSource[A]]
      implicitly[StSource.Aux[A, _] =:= StSource[A]]
      implicitly[StSource[A] =:= StSource.Aux[A, _]]
    }
    

    https://scala-lang.org/files/archive/spec/2.13/03-types.html#compound-types

    复合类型 ?1 with ... with ??{?} 表示具有在组件类型 ?1,...,?? 和细化 {?} 中给出的成员的对象。细化 {?} 包含声明和类型定义。如果一个声明或定义覆盖了组件类型?1,...,??之一中的声明或定义,则应用通常的覆盖规则;否则声明或定义被称为“结构性的”。

    另请参阅如何使用精炼类型的示例:

    https://typelevel.org/blog/2015/07/19/forget-refinement-aux.html

    How can I have a method parameter with type dependent on an implicit parameter?

    When are dependent types needed in Shapeless?

    Why is the Aux technique required for type-level computations?

    Understanding the Aux pattern in Scala Type System

    Enforcing that dependent return type must implement typeclass

    当定义像 trait 或类这样的类型时,类的主体是由类本身表示的类型构造函数的一部分吗?里面的方法怎么了?

    你可以替换

    def apply[A, S0](i: S0)(f: S0 => (A, S0)): Aux[A, S0] =
      new StSource[A] {
        override type S = S0
        override def init = i
        override def emit(s: S0) = f(s)
      }
    

    又名

    def apply[A, S0](i: S0)(f: S0 => (A, S0)): StSource[A] {type S = S0} =
      new StSource[A] {
        override type S = S0
        override def init = i
        override def emit(s: S0) = f(s)
      }
    

    def apply[A, S0](i: S0)(f: S0 => (A, S0)): StSource[A] {
      type S = S0
      def init: S
      def emit(s: S): (A, S)
    } =
      new StSource[A] {
        override type S = S0
        override def init = i
        override def emit(s: S0) = f(s)
      }
    

    但没有任何意义,因为类型保持不变

    def test[A, S0] = {
      implicitly[(StSource[A] {
        type S = S0
        def init: S
        def emit(s: S): (A, S)
      }) =:= (StSource[A] {type S = S0})]
    }
    

    当您将type S = S0 添加到您提供附加信息的类型时(该类型S 是特定的)但是当您将def init: Sdef emit(s: S): (A, S) 添加到您不提供附加信息的类型时(方法@987654346 @、emit 的存在从类StSource[A] 的定义中可以清楚地看出)。

    其他情况是如果类被定义为just

    sealed abstract class StSource[A] {
      type S
    }
    

    甚至

    sealed abstract class StSource[A]
    

    然后

    StSource[A] {
      type S = S0
      def init: S
      def emit(s: S): (A, S)
    }
    

    将是不同于 StSource[A]StSource[A] {type S = S0} 的类型(它们的子类型)。这将是一个结构类型(initemit 的存在将使用运行时反射进行检查)。这里

    {
      type S = S0
      def init: S
      def emit(s: S): (A, S)
    }
    

    是细化但不是类型细化。

    defs (init, emit) 不同,类型成员没有运行时表示(除非您将它们持久化,例如使用TypeTags),因此使用类型细化不会产生运行时开销。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-11
      • 2022-01-05
      相关资源
      最近更新 更多