簡體   English   中英

Scala 中的上下文綁定

[英]Context bound in 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

我們正在做的是說 - 有一個T類型的值t ,我們對此知之甚少,但我們所知道的是有一個Sample類型類實例可用於它。 這允許我們做t.getSample

現在,最終為您的問題提供答案:

在您的代碼中,您正在混淆事物。 你的T實際上被稱為Int 您打算使用Int類型,但您所做的是將泛型參數命名為Int 我本可以用更少的文字來回答這個問題,但我想也許你會發現更大的圖景很有趣,而不是僅僅指出錯誤。

名為Int的類型參數不代表具體的整數類型scala.Int 相反,類型參數被賦予與具體類型相同的名稱Int只是一個令人困惑的巧合。 如果你給它一些其他的名字,比如T

def method[T: Sample](a: T): T = a * a

錯誤消息應該更有意義。 現在我們看到*沒有為T定義,因為Sample類型類還沒有提供這樣的能力。 這是正確的語法用法可能看起來如何使用的示例

trait Sample[T] {
  def mult(a: T, b: T): T
}

def method[T: Sample](a: T): T = implicitly[Sample[T]].mult(a, a)
def method[T](a: T)(implicit ev: Sample[T]): T = ev.mult(a, a)

您還可以查看提供開箱即用功能的Numeric類型類

def method[T](a: T)(implicit num: Numeric[T]): T = num.times(a, a)

您的方法有一個名為Int的類型參數,它遮蔽了實際的Int ,就像定義一個普通變量會遮蔽外部作用域的某些東西一樣。 如果您刪除上下文綁定,也會發生同樣的情況。

您可能正在嘗試做的事情更接近以下內容:

trait Sample[A] {
  def someOperation(a1: A, a2: A): A
}

implicit object IntSample extends Sample[Int] {
  override def someOperation(a1: Int, a2: Int): Int = a1 * a2
}

def method[T: Sample](t: T) = implicitly[Sample[T]].someOperation(t, t)

method(4) // compiles and returns 16
//method("4") // doesn't compile, no implicit instance of Sample[String] in scope

您可以在 Scastie 上使用此代碼

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM