Scala中的上下文绑定
我正在学习 Scala 中的上下文绑定。
在下面的代码中,我对整数参数调用乘法运算符。但它会出错。'a' 被视为类型参数;但实际上并不符合我的理解。有人可以帮忙吗。
scala> class Sample[T]
defined class Sample
scala> def method[Int:Sample](a:Int) = a * a
<console>:12: error: value * is not a member of type parameter Int
def method[Int:Sample](a:Int) = a * a
谢谢!
回答
上下文边界是隐式泛型参数的语法糖,这些参数由您正在使用的某种类型参数化。这个概念也被称为“类型类”。您定义一些通用特征,例如您的Sample[T],然后为 的各种具体值提供该特征的隐式(!)实例T。我们称它们为“类型类实例”。
为什么是隐式?这是Scala用来实现类型类机制的一个实现细节;类型类也存在于例如 Haskell 中,但机制本身有点不同。无论如何,您可以定义一个方法,例如您的def method,它需要某个类型的类型类实例。并且您可以使用上下文绑定语法或使用更详细和更明确的隐式参数标准语法来执行此操作。
您的定义正在使用上下文绑定。但是您的示例有问题,如编译错误所示。让我们首先看一个正确使用类型类概念的正确示例。
// type class definition:
trait Sample[T] {
def getSample: T
}
// type class instance(s):
object Sample {
implicit val sampleInt: Sample[Int] =
new Sample[Int] { def getSample = 42 }
}
现在的用法:
import Sample._
// using the context bound syntax
def method1[T : Sample](t: T) = t.getSample
// not using the context bound syntax
def method2(t: T)(implicit ev: Sample[T]) = t.getSample
我们正在做的是说 - 有一些ttype值T,我们对此知之甚少,但我们所知道的是有一个Sample类型类实例可用于它。这让我们可以做到t.getSample。
现在,最终为您的问题提供答案:
在您的代码中,您正在混淆事物。你T实际上被称为Int. 您打算使用该Int类型,但您所做的是将您的泛型参数命名为Int。我本可以用更少的文字来回答这个问题,但我想也许你会发现更大的图景很有趣,而不仅仅是指出错误。