scala: operation overload and implicit conversion clarification - scala

Here is a code sample. Not sure why I am getting error when using multiplication.
Should I add implicit conversion to Int ? Sure the answer is simple!!
Thanks
class Fraction(val x:Int, val y:Int)
{
def X = x
def Y = y
implicit def int2Fraction(n: Int) = Fraction(n, 1)
def *(that: Fraction) : Fraction = new Fraction(that.X * X, that.Y * Y)
}
object Fraction {
def apply(x: Int, y: Int) = new Fraction(x, y)
}
val x : Int = 3
val result = x * Fraction(4, 5)
println( result.X )

Your implicit conversion function is a member of the Fraction class - so it can't be called without an instance of Fraction. If you move it to the object, it would work as expected:
object Fraction {
def apply(x: Int, y: Int) = new Fraction(x, y)
implicit def int2Fraction(n: Int) = Fraction(n, 1)
}

For an implicit conversion to take place, it needs to be in scope. Try taking it outside the class like this:
implicit def int2Fraction(n: Int) = Fraction(n, 1)
class Fraction(val x:Int, val y:Int)
{
def X = x
def Y = y
def *(that: Fraction) : Fraction = new Fraction(that.X * X, that.Y * Y)
}
object Fraction {
def apply(x: Int, y: Int) = new Fraction(x, y)
}
You can also put it inside the companion object; the compiler searches there automatically.

Related

How to reduce the unwanted type parameter in a generic method?

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

Overload private constructor with polymorphic arguments in Scala

I'm curious what the best solution to something like this is in Scala:
class MyClass private (x: Any, y: Int) {
def this(x: Int, y: Int) = this(x, y)
def this(x: String, y: Int) = this(x, y)
}
val x0 = new MyClass(1, 1)
val x1 = new MyClass("1", 1)
//val x2 = new MyClass(1.0, 1) // Correctly doesn't typecheck
The error below doesn't make a lot of sense to me, because it appears that a viable constructor is defined before the auxiliary constructor:
Error:(3, 31) called constructor's definition must precede calling constructor's definition
def this(x: Int, y: Int) = this(x, y)
^
For more context, I'm actually trying to deal with JavaScript APIs in Scala.js with functions that take a parameter that can be either a String or as js.Object, but I think this exemplifies the issue.
Ascribing the type to Any explicitly will help:
class MyClass private (x: Any, y: Int) {
def this(x: Int, y: Int) = this(x: Any, y)
def this(x: String, y: Int) = this(x: Any, y)
}
In your case, the constructors would call themselves recursively, which is obviously nonsensical.
I never worked with Scala-js, but could this solve your problem:
class MyClass private (x: Any, y: Int)
object MyClass{
def apply(x:Int,y:Int) = new MyClass(x,y)
def apply(x:String, y:Int) = new MyClass(x,y)
}
val x0 = MyClass(1, 1)
val x1 = MyClass("1", 1)
//val x2 = new MyClass(1.0, 1) // Correctly doesn't typecheck

Why doesn't Function2 have an andThen method?

Why does andThen only exist for single argument functions in Scala?
The following code works:
val double = (x: Int) => x * 2
val timesFour = double andThen double
But why is there no andThen method for multi argument functions?
val multiply = (x: Int, y: Int) => x * y
val multiplyAndDouble = multiply andThen double
<console>:10: error: value andThen is not a member of (Int, Int) => Int
Surely it is trivial to add this method. Is there a reason it been omitted from the standard library?
I have just noticed it is easy to work around with the following:
val multiplyAndDouble = multiply.tupled andThen double
val res = multiplyAndDouble(1, 3) // res = 6
I can't speak as to why Function2 doesn't supply and andThen, but Scalaz defines Functor instances for functions of various arities where map is equivalent to andThen, meaning you could write
val multiplyAndDouble = multiply map double
There is a similar question here:
Scala API 2.10.*: Function2.andThen what happened to?, but there is also no answer. In my opinion it is possible. Here is working example for Scala 2.11.1:
object TestFunction2 {
def main(args: Array[String]): Unit = {
val double = (x: Int) => x * 2
val timesFour = double andThen double
println(timesFour(2)) // prints 8
val multiply = (x: Int, y: Int) => x * y
val multiplyAndDouble = multiply andThen double
println(multiplyAndDouble(1, 3)) // prints 6
}
implicit def toFunc2(function2: Function2[Int, Int, Int]): Func2[Int, Int, Int] = {
new Func2[Int, Int, Int] {
def apply(v1: Int, v2: Int): Int = function2(v1, v2)
}
}
}
trait Func2[-T1, -T2, +R] extends Function2[T1, T2, R] {
def andThen[A](g: R => A): (T1, T2) => A = { (x, y) => g(apply(x, y)) }
}
Another way to write theons's answer is to use:
val multiplyAndDouble = double compose multiply.tupled
val result = multiplyAndDouble(2, 6) // res 24

Using implicit objects within classes

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

How can I remove this extra type parameter?

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))