代码之家  ›  专栏  ›  技术社区  ›  jpalecek

Scala中的类型参数与成员类型

  •  10
  • jpalecek  · 技术社区  · 17 年前

    一种方法是将关联的类型设置为类型参数。这种方法的优点是我可以规定类型的变化,并且我可以确保子类型不会改变类型。缺点是,我无法从函数中的类型推断类型参数。

    第二种方法是使关联类型成为第二种类型的成员,这有一个问题,即我不能规定子类型关联类型的界限,因此,我不能在函数参数中使用该类型(当x:x,x#t可能与x.t没有任何关系时)

    一个具体的例子是:

    trait DFA[S] { /* S is the type of the symbols in the alphabet */
      trait State { def next(x : S); }
      /* final type Sigma = S */
    }
    

    我想创建一个函数,在输入序列上运行这个DFA,我想

    • <% Seq[alphabet-type-of-the-dfa] 作为输入序列类型
    • 函数调用方不需要指定类型参数,所有类型参数都必须进行推断
    • 我希望使用具体的DFA类型调用函数(但是如果有一个解决方案,其中函数没有DFA的类型参数,则可以)
    • 字母表类型必须是无约束的(即,对于Char以及未知的用户定义类,必须有DFA)
    • 具有不同字母表类型的DFA不是子类型

    def runDFA[S, D <: DFA[S], SQ <% Seq[S]](d : D)(seq : SQ) = ....
    

    这是可行的,除了这里没有推断类型S,所以我必须在每个调用站点上编写整个类型参数列表。

    def runDFA[D <: DFA[S] forSome { type S }, SQ <% Seq[D#Sigma]]( ... same as above
    

    这不起作用(对类型D的循环引用无效??(是什么?)

    def runDFA[D <: DFA, SQ <% Seq[D#Sigma]]( ... same as above
    

    dfa.Sigma ,得到 D#Sigma "

    3 回复  |  直到 17 年前
        1
  •  3
  •   jpalecek    17 年前

    此外,Jorge所说的关于D上的类型参数,并使其成为DFA上的一种方法。由于Scala中内部类的工作方式,我会 将runDFA放在DFA上。在依赖路径的类型工作之前,处理一些外部类的内部类可能有点麻烦。

    trait DFA[S]{
      ...
    
      def runDFA(seq : Seq[S]) = ...
    }
    

    而runDFA突然间就很容易推断出其类型参数:它没有任何类型参数。

        2
  •  3
  •   Jorge Ortiz    17 年前

    Scala的类型推断有时会留下很多不足之处。

    def run[SQ <% Seq[S]](seq: SQ)
    

    def runDFA[S, SQ <% Seq[S]](d: DFA[S])(seq: SQ) = ...
    
        3
  •  0
  •   jhegedus    9 年前

    关于两者的区别的一些有用信息:

    不成形的 guide :

    例如,如果没有类型参数,则无法生成依赖类型

    trait Generic[A] {
      type Repr
      def to(value: A): Repr
      def from(value: Repr): A
    }
    
    import shapeless.Generic
    def getRepr[A](value: A)(implicit gen: Generic[A]) =
      gen.to(value)
    

    这里是返回的类型 to 取决于输入类型 A (因为提供的隐式依赖于 A.

    case class Vec(x: Int, y: Int)
    case class Rect(origin: Vec, size: Vec)
    getRepr(Vec(1, 2))
    // res1: shapeless.::[Int,shapeless.::[Int,shapeless.HNil]] = 1 :: 2 ::
         HNil
    getRepr(Rect(Vec(0, 0), Vec(5, 5)))
    // res2: shapeless.::[Vec,shapeless.::[Vec,shapeless.HNil]] = Vec(0,0)
         :: Vec(5,5) :: HNil
    

    trait Generic2[A, Repr]
    def getRepr2[A, R](value: A)(implicit generic: Generic2[A, R]): R =
      ???
    

    我们必须将所需的Repr值作为 类型参数,有效地使getRepr无效。直觉 类型成员可用作输出。

    请看不成形的 详情请参阅。

    推荐文章