我试图在斯卡拉模拟代数半环。我遇到了类型转换问题,这使得看起来不可能在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'可能是最接近的。 –