I am trying sample programs on Scala implicits. I am trying to implement one solution from the "Scala for the Impatient" book.
I have written as Fraction class having two member variables numerator and denominator with an operation overloading method "*(fraction)", so that we can call multiplication on Fraction objects like fration1 * fraction2 * fraction3.
Now, I tried to implement intToFraction and fractionToInt implicit methods, so that we can also write syntax like 2fraction13. I tried implementing those methods in companion object of Fraction class. But those methods are not getting called.
As suggested by Scala docs, Scala compiler will try to find out implicit implementation in the companion object. Here, we are performing operation on objects of Fraction class, so I assume, implicits declared in Fraction should have been called automatically. I also tried by importing implicit methods explicitly but it did not work.
Please find code snippet below for your reference.
package com.example.implicits.conversion
object ImplicitConversionTester extends App {
val f1 = Fraction(4,2)
val result = 2 * f1
println(s"${f1 * f1}")
println(s"${result}")
}
class Fraction(val numerator : Int,val denominator : Int) {
def *(fraction : Fraction): Fraction = {
println("##### Call to operator overloading *")
Fraction(this.numerator*fraction.numerator, this.denominator*fraction.denominator)
}
override def toString: String = s"Fraction($numerator,$denominator) ===== ${numerator/denominator}"
}
object Fraction {
def apply(numerator: Int, denominator: Int): Fraction = new Fraction(numerator, denominator)
implicit def intToFraction(num : Int) = {
println("##### intToFraction")
Fraction(num,1)
}
implicit def fractionToInt(fr : Fraction) = {
println("##### fractionToInt")
fr.numerator/fr.denominator
}
}
any suggestion to fix this problem appreciated!
You are right that the scala compiler looks for the implicit first in
current scope then
in companion scope then
in imported scope
And in your case compiler looking for the implicit in the scope of the main singleton object ImplicitConversionTester and it will not find anything since there is no any implicit available. If you import the implicit then it should work -
object Implicit extends App {
import Fraction._
class Fraction(val numerator : Int,val denominator : Int) {
def * (fraction : Fraction): Fraction = {
println("##### Call to operator overloading *")
Fraction(this.numerator*fraction.numerator, this.denominator*fraction.denominator)
}
}
object Fraction {
def apply(numerator: Int, denominator: Int): Fraction = new Fraction(numerator, denominator)
implicit def intToFraction(num : Int) = {
println("##### intToFraction")
Fraction(num,1)
}
implicit def fractionToInt(fr : Fraction) = {
println("##### fractionToInt")
fr.numerator/fr.denominator
}
}
println(Fraction(1,2) * 2)
}
The problem was in the declaration of the implicit methods without explicitly mentioned return types. I did not mention the return type in the code snippet above. Implicits are working fine after adding the function return type. So, There is no need to explicitly import the implicit functions in ImplicitConversionTester class to fix the problem.
Below is the updated fraction class to fix the error:
class Fraction(val numerator : Int,val denominator : Int) {
val test = 2
def *(fraction : Fraction): Fraction = {
println("##### Call to operator overloading *")
Fraction(this.numerator*fraction.numerator, this.denominator*fraction.denominator)
}
override def toString: String = s"Fraction($numerator,$denominator) ===== ${numerator/denominator}"
}
object Fraction {
def apply(numerator: Int, denominator: Int): Fraction = new Fraction(numerator, denominator)
implicit def intToFraction(num : Int) : Fraction = { // RETURN TYPE FRACTION
println("##### intToFraction")
Fraction(num,1)
}
implicit def fractionToInt(fr : Fraction) : Int = { // ADDED RETURN TYPE INT
println("##### fractionToInt")
fr.numerator/fr.denominator
}
}
Sharing below more details about how Scala compiler looksup the implicit conversion. Below image is taken from the book "Scala for the Impatient".
As mentioned in the book, Scala compiler gives first preference to companion object of the source or the target type.
Here, What is source and target type that depends on the order of expression. For example, if the expression is "2*Fraction(2,4)", the expression is evaluated from left to right. Int "2" has already implementation present for multiplication method (*). So, compiler tries to find implicit conversion from "Fraction to Int" in "Int" type first. As "Int" type does not have any implementation for "Fraction to Int", compiler will lookup companion object of Fraction class where it finds a method "fractionToInt". In this example, target type is Int and Source type is Fraction.
Consider the example of expression "Fraction(2,4)*2", Here as the Fraction class has implementation available for multiplication "*", compiler tries to find implicit for converting Int to Fraction. So target type is Fraction and Source type is Int. As there is no such implicit method/class present in Int class, compiler looksup Fraction companion object and finds "IntToFraction" implicit.
Related
In Scala, I want to generate some aliases for basic types, and then implement conversions through a type class. This is both useful for me, and an opportunity to understand type classes. The code is the following:
type Index = Int
val Index = Int
type Integer = Int
val Integer = Int
type Real = Double
val Real = Double // to have companion object of Double also be the companion object of Real
trait Convertible[A] {
def toIndex(a: A): Index
def toInteger(a: A): Integer
def toReal(a: A): Real
}
implicit val ConvertibleIndex: Convertible[Index] = new Convertible[Index] {
def toIndex(i: Index) = i
def toInteger(i: Index) = i
def toReal(i: Index) = i.toDouble
}
implicit val ConvertibleInteger: Convertible[Integer] = new Convertible[Integer] {
def toIndex(i: Integer) = i
def toInteger(i: Integer) = i
def toReal(i: Integer) = i.toDouble
}
implicit val ConvertibleReal: Convertible[Real] = new Convertible[Real] {
def toIndex(r: Real) = r.toInt
def toInteger(r: Real) = r.toInt
def toReal(r: Real) = r
}
implicit val ConvertibleString: Convertible[String] = new Convertible[String] {
def toIndex(s: String) = s.toInt
def toInteger(s: String) = s.toInt
def toReal(s: String) = s.toDouble
}
implicit class ConvertibleSyntax[A](a: A)(implicit val c: Convertible[A]) {
def toIndex = c.toIndex(a)
def toInteger = c.toInteger(a)
def toReal = c.toReal(a)
}
Consider now:
val a = 3.toReal
val b = 3.0.toReal
val c = "3".toReal
The statement for a does not compile, with the compilation error: method toReal is not a member of Int. But, for the b and c statements, the implicit conversion to ConvertibleSyntax is properly done.
Why is the implicit conversion not working on Int, but is working on Double and String ?
Because you define ambiguous implicits for Index and Integer (both Int).
Which one should be chosen by compiler?
I think you might be a little confused about how Scala does implicit conversions. (A common mistake, as implicit is a little overused.)
I think that what you want, first of all, is an implicit conversion function - or even an implicit class. Here's how you could do this using the latter:
Note: Int, Index and Integer are treated identically, so are Real and Double, confusing matters somewhat, so I've pared this down to something that will work. Also, Convertible does not need to be generic as its conversion functions need no arguments. Finally, you shouldn't have both type and val declarations for your types.
type Index = Int
type Integer = Int
type Real = Double
trait Convertible {
def toIndex: Index
def toInteger: Integer
def toReal: Real
}
// Implicit classes cannot be defined in top-level scope, so they belong to an object.
object Implicits {
implicit class ConvertibleInt(i: Int)
extends Convertible {
override def toIndex = i
override def toInteger = i
override def toReal = i.toDouble
}
implicit class ConvertibleDouble(d: Double)
extends Convertible {
override def toIndex = d.toInt
override def toInteger = d.toInt
override def toReal = d
}
implicit class ConvertibleString(s: String)
extends Convertible {
override def toIndex = s.toInt
override def toInteger = s.toInt
override def toReal = s.toDouble
}
}
Now try this:
import Implicits._
val a = 3.toReal
val b = 3.0.toReal
val c = "3".toReal
What's happening here? Well, the implicit class declarations define classes that decorate the sole constructor argument with additional functions. If the compiler sees that you're trying to call a method on a type that doesn't have that method, it will look to see if there's an implicit conversion, in scope, to a type that does. If so, it is used and the function is called; if not, you get a compiler error. (The import statement is used to bring the classes into your current scope.)
So, for example, when the compiler sees "3".toReal it firstly determines that "3" is a String. Since this type doesn't have a .toReal member, it tries to find a conversion from a String to a type that does have such a member. It finds the ConvertibleString implicit class that takes a String argument and provides a .toReal method. Yay! So the compiler creates an instance of this class by passing "3" to ConvertibleString's constructor, then calls .toReal on the result.
On the other hand, when implicit is used with a value, it tells the compiler that the value is a default for any matching implicit arguments of the same type that are not provided. NEVER USE implicit WITH A PRIMITIVE OR COMMON LIBRARY TYPE!
For example:
final case class Example(i: Int)
// Default.
implicit val nameCanBeAnythingAtAll = Example(5)
// Function with implicit argument.
def someFunc(implicit x: Example): Unit = println(s"Value is $x")
Now, if you write something like this:
someFunc
the output will be Value is Example(5).
implicit values and arguments are an advanced topic, and I wouldn't worry about how they're used right now.
I am learning Scala language features. I declare a class with a type parameter.
class Pair[+T](val first: T, val second: T){
// T is a covariant type. So an invariance R is introduced.
def replaceFirst[R >: T](newFirst: R) = {
new Pair(newFirst, second)
}
override def toString = "(" + first + ", " + second + ")"
}
Class Pair has a generic function replaceFirst. I declare a new class NastyDoublePair which extends Pair[Double]. And I'd like to override the generic function replaceFirst. Here is the compile error code:
class NastyDoublePair(first: Double, second: Double) extends Pair[Double](first, second){
override def replaceFirst(newFirst: Double): Pair[Double] = {
new Pair[Double](newFirst, second)
}
}
The compile error is below
Ch17.scala:143: error: method replaceFirst overrides nothing.
Note: the super classes of class NastyDoublePair contain the following, non final members named replaceFirst:
def replaceFirst[R >: Double](newFirst: R): ch17.p9.Pair[R]
override def replaceFirst(newFirst: Double): Pair[Double] = {
^
However, if I change the function replaceFirst to
def replaceFirst(newFirst: T) = {
new Pair(newFirst, second)
}
besides, change the Pair[+T] to Pair[T]. Everything goes well.
How can I fix the compile error, even if I'd like to set type parameter T to a covariant type. Otherwise, there is no solution to my case. I must use an invariant type parameter, not Pair[+T] but Pair[T]
Thanks for sharing your idea. Best wishes.
This happens because the type parameters change in NastyDoublePair, you can make this compile like follows:
class NastyDoublePair(first: Double, second: Double) extends Pair[Double](first, second){
override def replaceFirst[R >: Double](newFirst: R) = {
new Pair(newFirst, second)
}
}
Given a type which has a "converter", I would like to have automatic conversion on method call using this type's companion object. That is, given the following definition,
case class Converted(name: String)
trait Converter[A] {
def perform: Converted
}
implicit val StringConverter = new Converter[String] {
def perform = Converted("String")
}
make the following code to work:
implicit def toConverter(a: String.type): Converted =
implicitly[Converter[String]].perform // Error: `Found String.type, required AnyRef`
def f(needsConverted: Converted) = ???
f(String) // <- That's what I would like to be able to write.
But this fails and both attempts for conversion fail. Note that I cannot change f because it is provided by a third-party library and there are many of them.
Can I make f(String) compile using implicits?
If not possible for Strings, what about classes which do have a companion object, can I do this generically like:
object TheClass
case class TheClass()
implicit val TheClassConverter = new Converter[TheClass] {
def perform = Converted("TheClass")
}
implicit def toConverter[A: Converter](a: A.type): Converted =
implicitly[Converter[A]].perform // Error: `Not found value A`
implicit def toConverter(a: TheClass.type): Converted =
implicitly[Converter[TheClass]].perform // This works but is not generic
f(TheClass) // This works.
Can I make the first toConverter to compile ?
Instead of defining an implicit instance for the type MyClass you can define an implicit instance for the companion type MyClass.type.
implicit val TheClassConverter: Converter[MyClass.type] = new Converted[MyClass.type] {
def perform = Converted("MyClass")
}
Can I make f(String) compile using implicits?
No. You can define a value called String, of course, but it won't be related to the type String.
implicit toConverter[A: Converter](a: A.type): Converted =
implicitly[Converter[A]].perform
A in A.type must be a value; it is not related to the type parameter A.
In fact, so far as Scala's type system is concerned, there is no relationship between a class/trait and its companion object. So you can't do what you want generically.
Of course, if you don't insist on using () instead of [], it becomes trivial:
def f1[A: Converter] = f(implicitly[Converter[A]].perform)
f1[String]
f1[TheClass]
Not sure, what are you trying to accomplish, but following works for me
case class Converted(name: String)
trait Converter[A] {
def perform: Converted
}
implicit def toConverted(name: String) = Converted("String")
implicit def toIntConverted(int: Int) = Converted("Int")
def f(needsConverted: Converted): String = needsConverted.name
f("some")
f(5)
Recently I've (finally) started using Scala's Numeric trait, which does wonders. For example:
def square[A](x: A)(implicit num: Numeric[A]): A = num.times(x, x)
Now I can square any number be it Double, Integer, BigDecimal, or what not. Yet what if I want to do some more advanced math? For example, my logistic function for Double numbers looks like this:
def logisticFunction(x: Double): Double = 1.0 / (1.0 + math.exp(-x))
I could do the adding and dividing easily (I'd just have to use trait Fractional instead of Numeric), but what about the exponent? I sure don't want to write my own exp function (or any arbitrary function which takes Double arguments).
So, my question is this: how do I convert my A to Double, do my maths on that, and then convert back to A. Is it even possible?
EDIT:
That's how the signature of my function should look like:
def logisticFunction[A](x: A)(implicit num: Fractional[A]): A =
/* Magic happens here */
I've figured out the part about converting to double, which is as easy as num.toDouble(x). However the problem of converting back to A remains.
I still doubt this approach is really useful. But with your description, you will want something like this:
type FromDouble[A] = Double => A
type ToDouble [A] = A => Double
def logisticFunction[A: FromDouble: ToDouble](x: A): A = 1.0 / (1.0 + math.exp(-x))
logisticFunction(0.5)
implicit def bigDecimalToDouble(b: BigDecimal) = b.toDouble
logisticFunction(BigDecimal(0.5))
Or with dedicated type class:
object FromDouble {
implicit object _Double extends FromDouble[Double] {
def apply(d: Double) = d
}
implicit object _BigDecimal extends FromDouble[BigDecimal] {
def apply(d: Double) = BigDecimal(d)
}
}
trait FromDouble[A] extends (Double => A)
object ToDouble {
implicit object _Double extends ToDouble[Double] {
def apply(d: Double) = d
}
implicit object _BigDecimal extends ToDouble[BigDecimal] {
def apply(b: BigDecimal) = b.toDouble
}
}
trait ToDouble[A] extends (A => Double)
def logisticFunction[A: FromDouble: ToDouble](x: A): A = 1.0 / (1.0 + math.exp(-x))
logisticFunction(0.5)
logisticFunction(BigDecimal(0.5))
You will need a type class that provides trigonometric functions such as exp. Scala's standard library does not go beyond Fractional. You could try to use Spire.
Example:
$ sbt core/console
import spire.math._
import spire.algebra._
import spire.implicits._
def logisticFunction[A](x: A)(implicit m: Field[A], t: Trig[A]): A =
m.one / (m.one + exp(-x))
logisticFunction(0.5)
logisticFunction(BigDecimal(0.5))
I'm having difficulty transitioning from the world of C++/Templates to scala. I'm used to being able to use any operation on a template parameter T that I want, as long as anything I use to instantiate T with supports those operations (compile-time Duck typing, basically). I cannot find the corresponding idiom in Scala that will allow me to define an abstract class with a single type parameter, and which expects a certain interface for type T.
What I have almost works, but I cannot figure out how to tell the abstract class (Texture[T <: Summable[T]]) that T supports conversion/construction from an Int. How can I add the implicit conversion to the trait Summable so that Texture knows T supports the conversion?
trait Summable[T] {
def += (v : T) : Unit
def -= (v : T) : Unit
}
object Int4 { implicit def int2Int4(i : Int) = new Int4(i, i, i, i) }
class Int4 (var x : Int, var y : Int, var z : Int, var w : Int) extends Summable[Int4] {
def this (v : Int) = this(v, v, v, v)
def += (v : Int4) : Unit = { x += v.x; y += v.y; z += v.z; w += v.w }
def -= (v : Int4) : Unit = { x -= v.x; y -= v.y; z -= v.z; w -= v.w }
}
abstract class Texture[Texel <: Summable[Texel]] {
var counter : Texel
def accumulate(v : Texel) : Unit = { counter += v }
def decrement() : Unit = { counter -= 1 } //< COMPILE ERROR HERE, fails to find implicit
}
class Int4Target extends Texture[Int4] {
var counter : Int4 = new Int4(0, 1, 2, 3)
}
You can define an implicit constructor parameter like this
abstract class Texture[Texel <: Summable[Texel]](implicit int2Texel: Int => Texel) {
//...
This essentially tells the compiler that in order to construct an instance of Texture, there must be an implicit conversion function available from Int to Texel. Assuming you have such a function defined somewhere in scope (which you do), you should no longer get a compile error.
Edit2: Ok I originally misread your code, you actually only need one implicit parameter from Int => Texel. Your code compiles for me with the above modification.
Edit: You'll actually need 2 conversion functions, one from Texel => Int and another from Int => Texel in order to properly reassign the var
A fundamental difference between C++ templates and anything in Scala is that C++ templates are compiled for each use -- that is, if you use a template with int and with double, then two different classes are compiled, and they are only compiled when some code actually makes use of it.
Scala, on the other hand, has separate compilation. Not as good as Java's, given JVM limitations, but still following the basic principle. So, if something has a type parameter, it's still compiled at declaration, and only one such class ever exists. That compiled code has to support all possible parameters than it can be called with, which makes for rather different restrictions than templates.
On the matter of traits and implicit conversions, traits do not support parameters, and implicit conversions (view bounds) are parameters. Instead, use a class.
It is not possible in scala to require an implicit conversion to exist for a type
parameter of a trait. There is a good reason for this. Suppose we defined a
trait like:
trait ATrait[T <% Int] {
def method(v: T) { println(v: Int) }
}
And then made instances of it in two places:
package place1 {
implicit def strToInt(s: String) = 5
val inst = new ATrait[String]
}
package place2 {
implicit def strToInt(s: String) = 6
val inst = new ATrait[String]
}
And then used these instances like:
val a = if (someTest) place1 else place2
a.method("Hello")
Should this print 5 or 6? That is, which implicit conversion should it use?
Implicits have to be found at compile time, but you don't know which implicit
conversion was present for the creation of the object.
In other words, implicits are provided by the scope in which they are used, not
by the objects they are used on; the latter would be impossible.
So, about your problem. Instead of using an implicit, you could use an ordinary
member:
trait Summable[T] {
def -= (v: T): Unit
def -= (v: Int) { this -= (encode(v)) }
def encode(i: Int): T
}
class Int4 (var x: Int, var y: Int, var z: Int, var w: Int) extends Summable[Int4] {
def -= (v : Int4) : Unit = { x -= v.x; y -= v.y; z -= v.z; w -= v.w }
def encode(i: Int) = Int4.int2Int4(i)
}
Now the decrement method compiles correctly.
Another way of saying this is, don't think of implicits as properties belonging
to a type (ie, "can be implicitly converted from an Int" isn't a property of
Int4). They are values, which can be identified using types.
Hope this helps.