【问题标题】:Impose more than one generic type constraint on a Scala type parameter对 Scala 类型参数施加多个泛型类型约束
【发布时间】:2014-07-13 02:46:02
【问题描述】:

我想使用 Scala 的上下文绑定模式做以下事情:

    class Polynomial[T: Ring] {
        def apply[X: Ring with Includes[T]](x: X): X = ...
        ...
    }

这是一个多项式类,它要求系数是Ring T 中的元素。当将此多项式应用于元素(求值)时,参数x 的类型必须是环,T 类型的元素可以隐式转换为X 类型。例如T = Double, X = SquareMatrix

如何在 Scala 中对泛型类型参数施加多个类型约束?

【问题讨论】:

  • 这里为什么需要上下文绑定? Ring 是一个类型类?也许你需要这样的东西:def apply[X: Ring with Includes[T], T <% X](x: X): X = ... view bound (
  • @wedens 是的。 Ring 是一个类型类,旨在使 Int、Double、... 符合它。
  • 所以,我的解决方案应该适用于这种情况
  • Includes 的定义是什么样的?
  • @sjrd trait Includes[A, B] {implicit def from(b: B): A }

标签: scala generics context-bound


【解决方案1】:

似乎[X: T] 语法不足以强加两个泛型类型约束。使用两个隐式参数解决了这个问题:

   def apply[X](x: X)(implicit ring: Ring[X], conv: Includes[X, T]): X = {
     var xi = ring.one
     var sum = ring.zero
     for (i <- 0 to degree) {
       sum += xi * conv.from(coef(i))
       xi *= x
     }
    return sum
   }

【讨论】:

    【解决方案2】:

    [X: T] 语法只是需要 T[X] 类型的隐式参数的语法糖。例如,下面的ff2 是相同的:

     def f[T: X]
     def f2[T](implicit xt: X[T])
    

    至于你的代码,如果你显式写出隐式参数,你将能够表达你的约束:

    class Polynomial[T: Ring] {
        def apply[X](x: X)(implicit xt: Ring[X] with Includes[T]): X = ...
    }
    

    请注意,您不会对XT 施加多个约束,您的约束对于上下文绑定的语法糖来说太复杂了。但是,Scala 确实允许您对类型参数施加任意数量的上下文边界,并且您也可以将它们与上限和下限结合起来:

    def f[T >: List[Int] <: AnyRef : Ordering : List] = ???
    

    【讨论】:

    • 我想让 X 符合 Ring[X] 和 Includes[T]。
    猜你喜欢
    • 2011-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多