我試圖在斯卡拉模擬代數半環。我遇到了類型轉換問題,這使得看起來不可能在Scala中做我想做的事情。我希望有人能指引我理解我誤解的Scala輸入系統的方面。如何在Scala中使用運行時工廠對象來實現半實現?
(請長設置爲這個問題承受的。我已經削減下來,就像我可以。)
半環超過其定義二進制加法(+)和乘法一組項目(*)運算符及其標識元素,分別稱爲零和一。例如,Integer Semiring定義在整數上,其中+和*是來自算術和零的標準操作,一個是整數0和1.一個更奇特的例子是布爾半環,它是根據值True和False定義的,其中+是邏輯或,*是邏輯與,零是假,一個是真。
爲了建模,我定義了一個特徵來指定適當的二元運算符。
trait SemiringElement {
/**
* The element type
*/
type E
/**
* The type returned by the the addition and multiplication operators
*/
type R <: SemiringElement
val value: E
def +(that: R): R
def *(that: R): R
override def toString = value.toString
}
案例類實例化特定半環的元素。例如,布爾半環看起來像這樣。
case class BooleanSemiringElement(init: Boolean) extends SemiringElement {
type E = Boolean
type R = BooleanSemiringElement
val value = init
def +(that: BooleanSemiringElement#R) = BooleanSemiringElement(value || that.value)
def *(that: BooleanSemiringElement#R) = BooleanSemiringElement(value && that.value)
}
我還有一個指定零和一個元素的Semiring特徵。
trait Semiring {
type E <: SemiringElement
/**
* The addition identity
*/
val zero: E
/**
* The multiplication identity
*/
val one: E
}
特定的半環對象返回零和一個適當類型的元素。
object BooleanSemiring extends Semiring {
type E = BooleanSemiringElement
val zero = BooleanSemiringElement(false)
val one = BooleanSemiringElement(true)
}
的半環的對象基本上是工廠單身知道如何返回適當類型的識別元素。
我希望能夠編寫一般用於半環元素的算法。我使用Semiring工廠對象,以便能夠在運行時指定特定的半環,而不是編譯時間。例如,假設我有一個對象在字符串和半環元素之間保持一個映射。
class ElementMap(s: Semiring) {
val m = mutable.Map[String, SemiringElement]()
}
如果我實例化這個,象這樣一個電話:
val x = new ElementMap(BooleanSemiring)
我想x.m是一個與字符串> BooleanSemiringElement地圖。問題是我所擁有的實際上是一個String-> SemiringElement映射。
scala> val x = new ElementMap(BooleanSemiring)
x: ElementMap = [email protected]
scala> x.m
res2: scala.collection.mutable.Map[String,SemiringElement] = Map()
scala> x.m("one") = BooleanSemiring.one
scala> x.m("one") + BooleanSemiring.one
<console>:12: error: type mismatch;
found : BooleanSemiring.one.type (with underlying type BooleanSemiring.BooleanSemiringElement)
required: _1.R where val _1: SemiringElement
x.m("one") + BooleanSemiring.one
^
如果我願意在編譯時指定類型,而不是運行時我可以做的元素類型的通用像這樣:
class ElementMap[BooleanSemiring]...
但後來我需要一個工廠方法來創建所有不同類型的ElementMap對象。將工廠智慧融入Semiring特質使其更具建築意義。我想可以說是這樣的:
class ElementMap(s: Semiring) {
val m = mutable.Map[String, s.E]()
}
是:創建一個從字符串由供給構造的半環對象返回的元素類型E的地圖。我無法弄清楚如何做到這一點。我嘗試了各種語法技巧和隱式轉換無濟於事。
有沒有辦法寫一個在運行時配置了Semiring構造函數參數的ElementMap,還是我採用了錯誤的方法?我是新來的Scala,並試圖以斯卡拉式的方式做事。我覺得自己已經在這裏闖入了一個角落,但我不確定這個失誤究竟在哪裏。
感謝。即席多態似乎確實是針對這種情況。我現在正在閱讀。斯卡拉茲有一個具體的例子來解決這個問題嗎? –
'Monoid'可能是最接近的。 –