Note that there are some explanatory texts on larger screens.

plurals
  1. POHow do I use a runtime factory object for a semiring implementation in Scala?
    primarykey
    data
    text
    <p>I am attempting to model algebraic semirings in Scala. I'm running into type conversion problems that make it appear that it is not possible to do what I want to do in Scala. I'm hoping someone can direct me to the aspect of Scala's typing system that I have misunderstood.</p> <p>(Please bear with the long setup for this question. I've pared it down as much as I can.)</p> <p>A semiring is a set of items over which is defined binary addition (+) and multiplication (*) operators and their identity elements, called zero and one, respectively. For example the Integer Semiring is defined over the integers where + and * are the standard operations from arithmetic and zero and one are the integers 0 and 1. A more exotic example is the Boolean Semiring, which is defined over the values True and False, where + is logical OR, * is logical AND, zero is False, and one is True.</p> <p>To model this I define a trait that specifies the appropriate binary operators.</p> <pre><code>trait SemiringElement { /** * The element type */ type E /** * The type returned by the the addition and multiplication operators */ type R &lt;: SemiringElement val value: E def +(that: R): R def *(that: R): R override def toString = value.toString } </code></pre> <p>Case classes instantiate elements of particular semirings. For example, the Boolean Semiring would look like this.</p> <pre><code>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 &amp;&amp; that.value) } </code></pre> <p>I additionally have a Semiring trait which specifies zero and one elements.</p> <pre><code>trait Semiring { type E &lt;: SemiringElement /** * The addition identity */ val zero: E /** * The multiplication identity */ val one: E } </code></pre> <p>Specific semiring objects return zero and one elements of the appropriate type.</p> <pre><code>object BooleanSemiring extends Semiring { type E = BooleanSemiringElement val zero = BooleanSemiringElement(false) val one = BooleanSemiringElement(true) } </code></pre> <p>The Semiring objects are essentially factory singletons that know how to return identity elements of the appropriate type.</p> <p>I want to be able to write algorithms that work with semiring elements in general. I use the Semiring factory objects in order to be able to specify a particular semiring at runtime rather than compile time. For example, say I have an object that maintains a map between strings and semiring elements.</p> <pre><code>class ElementMap(s: Semiring) { val m = mutable.Map[String, SemiringElement]() } </code></pre> <p>If I instantiate this with a call like so:</p> <pre><code>val x = new ElementMap(BooleanSemiring) </code></pre> <p>I would like x.m to be a String->BooleanSemiringElement map. The problem is what I have is actually a String->SemiringElement map.</p> <pre><code>scala&gt; val x = new ElementMap(BooleanSemiring) x: ElementMap = ElementMap@46cf97b scala&gt; x.m res2: scala.collection.mutable.Map[String,SemiringElement] = Map() scala&gt; x.m("one") = BooleanSemiring.one scala&gt; x.m("one") + BooleanSemiring.one &lt;console&gt;: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 ^ </code></pre> <p>If I was willing to specify the type at compile time rather than runtime I could make the element type a generic like so:</p> <pre><code>class ElementMap[BooleanSemiring]... </code></pre> <p>but then I'd need a factory method to create all the different kinds of ElementMap objects. Putting the factory smarts inside a Semiring trait makes more sense architecturally. What I want to be able to say is something like this:</p> <pre><code>class ElementMap(s: Semiring) { val m = mutable.Map[String, s.E]() } </code></pre> <p>that is: create a map from strings to the element type E returned by the Semiring object supplied to the constructor. I can't figure out how to do this. I've tried various syntactic tricks and implicit conversions to no avail.</p> <p>Is there a way write an ElementMap that is configured with a Semiring constructor parameter at runtime, or am I taking the wrong approach? I'm new to Scala and trying to do things in a Scala-esque manner. I feel like I've painted myself into a corner here, but I'm not sure exactly where the misstep lies.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload