I am trying to write code to represent polynomials within Scala. I need this code to be type polymorphic, so I am using implicits to deal with different types. I have:
case class Mono[T](degree: Int, coeff: T) {
def Degree: Int = return degree
def Coeff: T = return coeff
}
class Poly[T](private val terms: List[Mono[T]]) {
trait Semiring[T] {
def add(x:T, y:T): T
def mul(x:T, y:T): T
def exponent(x: T, n:Int): T
val unitA: T
}
implicit object IntSemiring extends Semiring[Int] {
def add(x: Int, y: Int): Int = x+y
def mul(x: Int, y: Int): Int = x*y
def exponent(x: Int, n:Int): Int = if(n==0) 1 else x*exponent(x, n-1)
val unitA: Int = 0
}
implicit object SetSemiring extends Semiring[Set[Int]] {
def add(x: Set[Int], y: Set[Int]): Set[Int] = x.union(y)
def mul(x: Set[Int], y: Set[Int]): Set[Int] = x.intersect(y)
def exponent(x: Set[Int], n: Int): Set[Int] = x
val unitA: Set[Int] = Set()
}
def eval(x: T)(implicit r: Semiring[T]): T = {
var termlist = terms
var sum = r.unitA
var expression = terms
while(!termlist.isEmpty) {
val term = expression.head
val power = r.exponent(x, term.Degree)
val termval = r.mul(power, term.Coeff)
sum = r.add(sum, termval)
termlist = termlist.tail
}
return sum
}
def add(that: Poly[T])(implicit r: Semiring[T]): Poly[T] = ...
def mul(that: Poly[T])(implicit r: Semiring[T]): Poly[T] = ...
}
I chopped out a few functions for brevity there. This compiles fine but when I try and use it I get some strange errors:
scala> val p1 = new Poly(List(Mono(0,1),Mono(1,2),Mono(2,1)))
p1: Poly[Int] = Poly#450ae3fb
scala> p1 eval 3
<console>:9: error: could not find implicit value for parameter r: p1.Semiring[Int]
p1 eval 3
^
I'm not sure how to fix it. Am I defining the implicit objects in the wrong place? I tried moving them outside the class but then the complier fails. Is there something else I need to do to get it to work properly?
Implicit resolution is done at the location where you call the function, not where you define it. You should import your implicits before calling p1.eval:
val p1 = new Poly(List(Mono(0,1),Mono(1,2),Mono(2,1)))
import p1._
p1 eval 3
Since your implicits are not really bound to an instance of Poly, you can define them outside Poly.
If you don't want to import explicitly the Semiring implicits, you can define them in the companion object of Semiring since Scala search for matching implicits in the companion object when they are missing:
case class Mono[T](degree: Int, coeff: T) {
def Degree: Int = return degree
def Coeff: T = return coeff
}
class Poly[T](private val terms: List[Mono[T]]) {
def add(that: Poly[T])(implicit r: Semiring[T]): Poly[T] = ...
def mul(that: Poly[T])(implicit r: Semiring[T]): Poly[T] = ...
}
trait Semiring {
def add(x:T, y:T): T
def mul(x:T, y:T): T
def exponent(x: T, n:Int): T
val unitA: T
}
object Semiring {
implicit object IntSemiring extends Semiring[Int] {
def add(x: Int, y: Int): Int = x+y
def mul(x: Int, y: Int): Int = x*y
def exponent(x: Int, n:Int): Int = if(n==0) 1 else x*exponent(x, n-1)
val unitA: Int = 0
}
implicit object SetSemiring extends Semiring[Set[Int]] {
def add(x: Set[Int], y: Set[Int]): Set[Int] = x.union(y)
def mul(x: Set[Int], y: Set[Int]): Set[Int] = x.intersect(y)
def exponent(x: Set[Int], n: Int): Set[Int] = x
val unitA: Set[Int] = Set()
}
}
Then you don't need to import them anymore:
val p1 = new Poly(List(Mono(0,1),Mono(1,2),Mono(2,1)))
p1 eval 3
Related
I want to implement some generic math functions with some flexible.
e.g. a function named meandot which declared as something like
object Calc {
def meandot[..](xs: Array[Left], ys: Array[Right])(implicit ..): Result
}
where meandot(xs, ys) = sum(x*y for x, y in zip(xs, ys)) / length
When I invoke the meandot without specialized type parameter, it should return a value with default type. e.g.
scala> Calc.meandot(Array(1, 2), Array(1, 1))
res0: Int = 1
If I invoke the meandot with specialized type parameter, it can return a proper value.
scala> Calc.meandot[Int, Int, Double](Array(1, 2), Array(1, 1))
res1: Double = 1.5
However, the first two type parameters in above are redundant. The only type I need to specialized is the return type. I want to invoke it simplified as
scala> Calc.meandot2(Array(1, 2), Array(1, 1))
res2: Int = 1
scala> Calc.meandot2[Double](Array(1, 2), Array(1, 1))
res3: Double = 1.5
And I found a way to implement it as following code, which using a proxy class MeanDotImp. But it seems not so elegant. So I wonder if there is any better solution to reduce the unwanted type parameter in a generic method?
trait Times[L, R, N] {
def times(x: L, y: R): N
}
trait Num[N] {
def zero: N = fromInt(0)
def one: N = fromInt(1)
def fromInt(i: Int): N
def plus(x: N, y: N): N
def div(x: N, y: N): N
}
abstract class LowTimesImplicits {
implicit val IID: Times[Int, Int, Double] = new Times[Int, Int, Double] {
def times(x: Int, y: Int): Double = x * y
}
}
object Times extends LowTimesImplicits {
implicit val III: Times[Int, Int, Int] = new Times[Int, Int, Int] {
def times(x: Int, y: Int): Int = x * y
}
}
object Num {
implicit val INT: Num[Int] = new Num[Int] {
def fromInt(i: Int): Int = i
def plus(x: Int, y: Int): Int = x + y
def div(x: Int, y: Int): Int = x / y
}
implicit val DOU: Num[Double] = new Num[Double] {
def fromInt(i: Int): Double = i
def plus(x: Double, y: Double): Double = x + y
def div(x: Double, y: Double): Double = x / y
}
}
object Calc {
def meandot[L, R, N](xs: Array[L], ys: Array[R])
(implicit t: Times[L, R, N], n: Num[N]): N = {
val total = (xs, ys).zipped.foldLeft(n.zero){
case(r, (x, y)) => n.plus(r, t.times(x, y))
}
n.div(total, n.fromInt(xs.length))
}
implicit class MeanDotImp[L, R](val marker: Calc.type) {
def meandot2[N](xs: Array[L], ys: Array[R])
(implicit t: Times[L, R, N], n: Num[N]): N = {
val total = (xs, ys).zipped.foldLeft(n.zero){
case(r, (x, y)) => n.plus(r, t.times(x, y))
}
n.div(total, n.fromInt(xs.length))
}
}
}
An alternative solution is similar to yours, but is a bit more straightforward: it first fixes the type parameter that you want to be able to set and then infers the other two. To achieve that we can declare a class with apply method:
class meandot[N] {
def apply[L, R](xs: Array[L], ys: Array[R])
(implicit t: Times[L, R, N], n: Num[N]): N = ??? // your implementation
}
Now, to avoid writing new meandot, we can define a method which just instantiates this class:
object Calc {
def meandot[N]: meandot[N] = new meandot[N]
}
Elegance of this approach is arguable, but it's quite simple and doesn't involve implicits. Here's a usage demo:
scala> Calc.meandot(Array(1,2,3), Array(4,5,6))
res0: Int = 10
scala> Calc.meandot[Double](Array(1,2,3), Array(4,5,6))
res1: Double = 10.666666666666666
I have the code that instance.get returns value, and based on the type I process accordingly.
instance.get match {
case v:Range => {
val sizeInBytes = util.conversion.Util.getBytesForBits(v.size)
val value = v.decode(contentByteArray.slice(index, index + sizeInBytes))
index += sizeInBytes
res(key) = value
}
case v:Encoding => {
val sizeInBytes = util.conversion.Util.getBytesForBits(v.size)
val value = v.decode(contentByteArray.slice(index, index + sizeInBytes))
index += sizeInBytes
res(key) = value
}
...
}
In the code, I have duplication for the Range and Encoding type. How can I merge the two cases?
I tried the | operator, but it doesn't work.
case v:Range | v:Encoding
This can't work, because Range.size and Encoding.size are two completely different methods despite the fact that they are named the same. And same is true for Range.decode and Edncoding.decode.
So, when you write v.size, the type of v has to be known, it has to be either v:Encoding or v:Range, not v:Encoding|v:Range.
How to fix this? Make a common trait like this:
trait SomethingWithDecodeAndSize {
def size: Int
def decode(bytes: Array[Byte]): Whatever
}
And then, change the definitions of Range and Encoding:
class Range extends SomethingWithDecodeAndSize { ... }
class Encoding extends SomethingWithDecodeAndSize { ... }
Now you can just do case v: SomethingWithDecodeAndSize => ... in your match clause.
Also ... Don't do instance.get, that's bad taste. Do instead
instance match {
Some(v: SomethingWithDecodeAndSize) => ...
}
Update
If you cannot modify the definitions of the original classes, you can use an extractor:
object SomethingWithDecodeAndSize {
def unapply(a: Any): Option[SomethingWithDecodeAndSize] = a match {
case r: Range => Some(new SomethingWithDecodeAndSize {
def size = r.size
def decode(bytes: Array[Byte]) = r.decode(bytes)
})
case r: Encoding => Some(new SomethingWithDecodeAndSize {
def size = r.size
def decode(bytes: Array[Byte]) = r.decode(bytes)
})
case _ => None
}
}
Now, you can do case Some(SomethingWithDecodeAndSize(v)) => ... in your match.
An alternate solution to #Dima's in case you can't change definition of Range and Encoding (and there is no supertype with required methods):
trait RangeOrEncoding {
def size: Int
def decode(bytes: Array[Byte]): Whatever
}
implicit def liftRange(r: Range): RangeOrEncoding = new RangeOrEncoding {
def size = r.size
def decode(bytes: Array[Byte]) = r.decode(bytes)
}
// similar conversion for Encoding
// can also be a local def
private def handleRangeOrEncoding(v: RangeOrEncoding) = {
val sizeInBytes = util.conversion.Util.getBytesForBits(v.size)
val value = v.decode(contentByteArray.slice(index, index + sizeInBytes))
index += sizeInBytes
res(key) = value
}
instance match {
case Some(v: Range) => handleRangeOrEncoding(v)
case Some(v: Encoding) => handleRangeOrEncoding(v)
...
}
I remember the cheerleaders in high school asking us, "How loose is your goose?"
scala> class C { def f(i: Int) = 2 * i }
defined class C
scala> class D { def f(i: Int) = 3 * i }
defined class D
scala> def test(x: Any) = x match { case y: { def f(i: Int): Int } => y.f(42) }
<console>:11: warning: a pattern match on a refinement type is unchecked
def test(x: Any) = x match { case y: { def f(i: Int): Int } => y.f(42) }
^
warning: there was one feature warning; re-run with -feature for details
test: (x: Any)Int
scala> test(new C)
res0: Int = 84
scala> test(new D)
res1: Int = 126
scala> test(42)
java.lang.NoSuchMethodException: java.lang.Integer.f(int)
at java.lang.Class.getMethod(Class.java:1786)
at .reflMethod$Method1(<console>:11)
at .test(<console>:11)
... 32 elided
I believe the answer was: "Loose, baby, loose."
Edit:
scala> import reflect.runtime._,universe._,language.reflectiveCalls
import reflect.runtime._
import universe._
import language.reflectiveCalls
scala> class C { def f(i: Int) = 2 * i }
defined class C
scala> class D { def f(i: Int) = 3 * i }
defined class D
scala> def f[A](a: A)(implicit tt: TypeTag[A]) = a match {
| case b: { def f(i: Int): Int }
| if tt.tpe <:< typeOf[{ def f(i: Int): Int }] =>
| b.f(42)
| }
<console>:19: warning: a pattern match on a refinement type is unchecked
case b: { def f(i: Int): Int }
^
f: [A](a: A)(implicit tt: reflect.runtime.universe.TypeTag[A])Int
scala> f(new C)
res0: Int = 84
scala> f(new D)
res1: Int = 126
scala> f(3) // now an ordinary MatchError
scala.MatchError: 3 (of class java.lang.Integer)
at .f(<console>:18)
... 32 elided
So you can express it as an ordinary type bounds:
scala> def f[A <: { def f(i: Int): Int }](a: A) = a.f(42)
f: [A <: AnyRef{def f(i: Int): Int}](a: A)Int
scala> f(new C)
res3: Int = 84
scala> f(17)
<console>:20: error: inferred type arguments [Int] do not conform to method f's type parameter bounds [A <: AnyRef{def f(i: Int): Int}]
f(17)
^
<console>:20: error: type mismatch;
found : Int(17)
required: A
f(17)
^
You still need to accept the cost of the reflective call, of course.
Why is the following implicit method not applied? And how can I achieve to automatically convert an instance of X to an instance of Y while having an implicit Conversion[X,Y] in scope.
trait Conversion[X, Y] {
def apply(x: X): Y
}
implicit object Str2IntConversion extends Conversion[String, Int] {
def apply(s: String): Int = s.size
}
implicit def convert[X, Y](x: X)(implicit c: Conversion[X, Y]): Y = c(x)
val s = "Hello"
val i1: Int = convert(s)
val i2: Int = s // type mismatch; found: String required: Int
Make your conversion extend Function1, then you don't need the helper method anymore:
trait Conversion[X, Y] extends (X => Y) {
def apply(x: X): Y
}
// unchanged
implicit object Str2IntConversion extends Conversion[String, Int] {
def apply(s: String): Int = s.size
}
// removed convert
// unchanged
val s = "Hello"
val i1: Int = convert(s)
val i2: Int = s
I currently have:
class X[+T: Numeric](val x: T)
abstract class M[N: Numeric, T <: X[N]] { // <- I'd like to remove N.
def apply(x: Int): T
final def row = (1 to 10).map(this(_))
}
I use it like this:
class Y(x: Double, val y: Double) extends X[Double](x)
class Z extends M[Double, Y] { // <- So that this is simpler.
def apply(x: Int) = new Y(0.0, 0.0)
}
It works like this:
object testapp {
// row is properly polymorphic, allowing access to Y.y
def main(args: Array[String]): Unit = (new Z).row.map(r => println(r.y))
}
I want Z to be simpler so that I can use M like:
class Z extends M[Y] {
def apply(x: Int) = new Y(0.0, 0.0)
}
or, even better:
class Z extends M[Double] { // i.e. Meaning apply can return
def apply(x: Int) = new Y(0.0, 0.0) // any subclass of X[Double]
}
Here are my Gist iterations to reach this point.
A third way in type params vs type members is to use both.
An advantage of a type member is that it doesn't pollute the signature of child classes. The type member can remain abstract if it is superfluous (even in a concrete class); and only the bottom class must define it if necessary.
import scala.collection.immutable.IndexedSeq
class X[+T: Numeric](val x: T)
abstract class M[+A: Numeric] {
type W <: X[A]
def apply(x: Int): W
final def row: IndexedSeq[W] = (1 to 10) map apply
def sumx: A = { // in terms of the underlying Numeric
val n = implicitly[Numeric[A]]
n fromInt (0 /: row)((s,w) => s + (n toInt w.x))
}
}
class Y(x: Double, val y: Double) extends X[Double](x)
class Z extends M[Double] {
type W = Y
def apply(x: Int) = new Y(0.0, 0.0)
}
def main(args: Array[String]): Unit = (new Z).row foreach (Console println _.y)
You didn't really need class M here:
class X[+T: Numeric](val x: T)
def row[W <: X[_]](c: => Int => W) = (1 to 10).map(c)
class Y(x: Double, val y: Double) extends X[Double](x)
def z = row(_ => new Y(0.0, 0.0))
def main(args: Array[String]): Unit = z.map(r => println(r.y))
If you want to keep M, you use same idea:
class X[+T: Numeric](val x: T)
abstract class M[W <: X[_]] {
def apply(x: Int): W
final def row = (1 to 10).map(this(_))
}
class Y(x: Double, val y: Double) extends X[Double](x)
class Z extends M[Y] {
def apply(x: Int) = new Y(0.0, 0.0)
}
def main(args: Array[String]): Unit = (new Z).row.map(r => println(r.y))
How does one go about implementing a subtype of Numeric[T]?
I have been looking for at guide on this but haven't found any.
Example of subtypes could be Rational or Complex?
Thanks in advance
Troels
An absolutely useless String Numeric:
trait StringIsNumeric extends Numeric[String] {
def plus(x: String, y: String): String = "%s+%s" format (x, y)
def minus(x: String, y: String): String = "%s-%s" format (x)
def times(x: String, y: String): String = "%s*%s" format (x, y)
def quot(x: String, y: String): String = "%s/%s" format (x, y)
def rem(x: String, y: String): String = "%s%%s" format (x, y)
def negate(x: String): String = "-%s" format (x)
def fromInt(x: Int): String = x.toString
def toInt(x: String): Int = 0
def toLong(x: String): Long = 0L
def toFloat(x: String): Float = 0.0f
def toDouble(x: String): Double = 0.0
}
implicit object StringIsNumeric extends StringIsNumeric with Ordering.StringOrdering
def x[T: Numeric](t1 : T, t2 : T) = {
val n = implicitly[Numeric[T]]
import n._
t1 * t2
}
scala> x("a","b")
res0: java.lang.String = a*b
I added Real to Scalaz, with instances Real[Double] and Real[Dual].
I found it convenient to make fromDouble implicit