我已經定義了一個特征Mergeable,它代表一個可以與另一個同類合并的值,但是我在正確宣告型別時遇到了麻煩。
trait Mergeable[T] {
def value: Option[T]
def merge(other: ???): ???
}
trait SummingInt extends Mergeable[Int] {
def merge(other: SummingInt): SummingInt = {
val sum = for {
i1 <- value
i2 <- other.value
} yield i1 i2
sum orElse this orElse other
}
}
trait MultiplyingInt extends Mergeable[Int] {
def merge(other: MultiplyingInt): MultiplyingInt = {
val product = for {
i1 <- value
i2 <- other.value
} yield i1 * i2
product orElse this orElse other
}
}
我想要求所有人都Mergeable定義一種方法,將其與另一種自己merge的方法合并。因此,將 a與 a合并是非法的。SummingIntMultiplyingInt
如果我選擇:
def merge(other: Mergeable[T]): Mergeable[T]
然后我就失去了只合并同類的保證。但是,如果我不定義mergeon Mergeable,那么我就無法撰寫這種讓我的生活變得更簡單的方法:
def mergeTwo[T <: Mergeable](first: T, second: T) = first merge second
即使mergeTwo可以保證first和second屬于同一型別,因此可以安全合并!
Scala 語言是否讓我可以merge在 ? 級別進行定義Mergeable?
uj5u.com熱心網友回復:
為了詳細說明評論,您要查找的不是子類而是typeclass。說您的值是 的實體是不準確的Mergeable,因為這意味著某種不現實的“全域”可合并功能。Mergeable相反,說這是一種可以應用于型別的能力是有道理的。也就是說,“型別Int是一個Mergeable”,而不是“每個Int本身都是可合并的”。
我將在這里使用 Scala 2 語法,因為您沒有提到 Scala 版本。請注意,Scala 3 中的某些語法已更改。
我們使用 trait 來描述我們的型別類。至關重要的是,這個特性不會被具體型別實作,比如Intor String。它將由我們組成的特殊單例物件來實作。
trait Mergeable[A] {
def merge(lhs: A, rhs: A): A
}
現在我們使用“隱式”為已知型別提供實體。關鍵詞。我們將given在 Scala 3 中使用。
implicit object IntIsMergeable extends Mergeable[Int] {
def merge(lhs: Int, rhs: Int) = lhs rhs
}
implicit object StringIsMergeable extends Mergeable[String] {
def merge(lhs: String, rhs: String) = lhs rhs
}
// Note: 'class' here since it's parameterized so it's not
// just one object.
implicit class ListIsMergeable[A] extends Mergeable[List[A]] {
def merge(lhs: List[A], rhs: List[A]) = lhs rhs
}
現在,如果我們想撰寫一個接受可合并物件并做某事的函式,我們使用隱式引數。假設我們想撰寫一個合并這三個引數的三個引數的函式。
def merge3[A](x: A, y: A, z: A)(implicit mergeable: Mergeable[A]): A =
mergeable.merge(mergeable.merge(x, y), z)
merge3是四個引數的函式:x、y、z和mergeable。當我們呼叫 時merge3,我們可以(根據我們的選擇)省略第四個引數,Scala 會自動找到一個具有正確型別的引數。因此,如果我們傳遞三個整數,它知道它需要 a Mergeable[Int],并且只有一個隱含的實體:IntIsMergeable我們之前寫的。關于如何有效和直觀地解決實體有很多科學問題,但這是基本思想。
撰寫人們會理解的良好型別類也有很多約定,例如提供apply呼叫隱式實體的 an 和提供擴展方法。如果你感興趣的話,Shapeless 這本書會詳細介紹其中的一些約定。
最后,正如評論中所暗示的,你Mergeable已經有了一個名字:它叫做Semigroup. 這是一個易于理解的數學物件,由Scalaz和Cats提供。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/463274.html
