The following outputs 0 instead of my desired result, which is 2.
This looks similar to this question, but here I am using parentheses everywhere.
object Test {
implicit def x = List(1, 2)
trait A[T] {
def res(): Int = 0
def makeResPlusOne(): Int = res() + 1 // All right
}
trait B[T] extends A[T] {
def res()(implicit y: List[T]) = y.size
}
class AA extends A[Int]
class BB extends B[Int]
}
val x: Test.A[Int] = new Test.BB
x.res() // Outputs 0 instead of 2.
I would like the last result to be obviously 2, the size of y, but it outputs 0.
If I add the keyword override to the method in B[T], it says that it overrides nothing.
If I add the implicit argument to the method res in A[T] like that ...
object Test {
implicit def x = List(1, 2)
trait A[T] {
def res()(implicit y: List[T]): Int = 0 // Added the implicit keyword.
def makeResPlusOne(): Int = res() + 1 // Fails to compile.
}
trait B[T] extends A[T] {
override def res()(implicit y: List[T]) = y.size
}
class AA extends A[Int]
class BB extends B[Int]
}
val x: Test.A[Int] = new Test.BB
x.res() // Error
... it raises the following error:
error: could not find implicit value for parameter y: List[Int]
What am I doing wrong ? How can I get the benefits of implicit values in subclasses and still being able to overload super methods ?
EDIT
It works if I import an implicit. However, I have the method makeResPlusOne(), which triggers the error in the second case, but not in the first. Please tell me how to properly define this method, which normally does not need an implicit at compile time.
_
error: could not find implicit value for parameter y: List[T]
def makeResPlusOne(): Int = res() + 1
^
You were close:
object Test {
implicit def list = List(1, 2)
trait A[T] {
def res()(implicit y: List[T]): Int = 0 // Added the implicit keyword.
}
trait B[T] extends A[T] {
override def res()(implicit y: List[T]) = y.size
}
class AA extends A[Int]
class BB extends B[Int]
}
import Test.list
val x: Test.A[Int] = new Test.BB
x.res() // Works!
You forgot to import the implicit list. Note that I have renamed the implicit to avoid conflict when importing with the variable x.
EDIT:
If you want def makeResPlusOne()(implicit y: List[T]): Int = res() + 1 you need to have an implicit List[T] in the scope, so you must add (implicit y: List[T]) as well.
object Test {
implicit def xx = List(1, 2)
trait A[T] {
def res()(implicit y: List[T]): Int = 0
def makeResPlusOne()(implicit y: List[T]): Int = res() + 1 // Works now.
}
trait B[T] extends A[T] {
override def res()(implicit y: List[T]) = y.size
}
class AA extends A[Int]
class BB extends B[Int]
}
import Test.xx // import the implicit list
val x: Test.A[Int] = new Test.BB
x.res() // Works
This code works fine for me (notice I changed your implicit from a def to a val):
object Test {
implicit val xx = List(1, 2)
trait A[T] {
def res()(implicit y: List[T]): Int = 0 // Added the implicit keyword.
}
trait B[T] extends A[T] {
override def res()(implicit y: List[T]) = y.size
}
class AA extends A[Int]
class BB extends B[Int]
val x: Test.A[Int] = new Test.BB
x.res()
}
Not sure if this still meets your needs with the changes though. The underlying issue really was that, as the compiler was telling you, you did not have an implicit List[Int] in scope. My example moved the x.res() call into the Test object therefore bringing it into scope, but you could also have just imported the existing implicit into scope as mentioned by #Stephane Godbillon.
Related
I notice when I'm trying to create an instance of a fooSemigroup, in version one the anonymous function creates an instance of fooSemigroup without instantiating a member of Foo, but when I try to do this without the SAM construct, I need to create a dummy instance of foo for the SemigroupOps to pull in the implicit value ev.
trait Semigroup[A] {
def combine(x: A, y: A): A
}
case class Foo(v: Int)
// vs 1
implicit val fooSemigroup: Semigroup[Foo] = (x: Foo, y: Foo) => Foo(x.v + y.v)
// vs 2
class fooSemigroup(foo: Foo) extends Semigroup[Foo] {
def combine(x: Foo, y: Foo) = Foo(x.v + y.v)
}
implicit val f: fooSemigroup = Foo(0)
implicit class SemigroupOps[A](x: A) {
def +(y: A)(implicit ev: Semigroup[A]): A = ev.combine(x, y)
}
Instead of implicit class
implicit class fooSemigroup(foo: Foo) extends Semigroup[Foo] {
def combine(x: Foo, y: Foo) = Foo(x.v + y.v)
}
try implicit object
implicit object fooSemigroup extends Semigroup[Foo] {
def combine(x: Foo, y: Foo) = Foo(x.v + y.v)
}
However as per Luis' advice favour implicit val instances over implicit object as otherwise resolution might result in ambiguous implicit values error, for example
trait SomeTrait[T] {
def f: T
}
trait ExtendedTrait[T] extends SomeTrait[T] {
def g: T
}
implicit object SomeStringObject extends SomeTrait[String] {
override def f: String = "from object f"
}
implicit object ExtendedStringObject extends ExtendedTrait[String] {
override def f: String = "from extended obj f"
override def g: String = "from extended obj g"
}
implicitly[SomeTrait[String]] // Error: ambiguous implicit values
where full error states
Error:(15, 77) ambiguous implicit values:
both object ExtendedStringObject in class A$A7 of type A$A7.this.ExtendedStringObject.type
and object SomeStringObject in class A$A7 of type A$A7.this.SomeStringObject.type
match expected type A$A7.this.SomeTrait[String]
def get$$instance$$res0 = /* ###worksheet### generated $$end$$ */ implicitly[SomeTrait[String]];}
^
I have been trying to create some sort of a typeclass and encountered problems with implicit resolution.
Basically I want to generate random data and adjust parameters of generation - interval for numbers, length and interval for arrays, etc.
Here is what I've got by now:
import scala.util.Random
trait PrimitiveGenerator[T <: AnyVal, Bounds] {
def generate(bounds: Bounds): T
def generatePossibly(bounds: Bounds): Option[T] = if (Random.nextDouble() < 0.5) None else Some(generate(bounds))
}
object PrimitiveGenerator {
def apply[A <: AnyVal](implicit impl: PrimitiveGenerator[A, _]) = impl
}
object Generators {
implicit object IntGenerator extends PrimitiveGenerator[Int, (Int, Int)] {
override def generate(bounds: (Int, Int) = (0, 1)): Int = Random.nextInt((bounds._2 - bounds._1) + 1) + bounds._1
}
}
object Test extends App {
import Generators._
PrimitiveGenerator[Int].generate((0, 1)) //error is here
}
In Intellij Idea this is failing with:
found : (Int, Int)
required: _$1 where type _$1
PrimitiveGenerator[Int].generate((0, 1))
I have an inkling that using underscore is wrong here, but how could I rewrite it to summon an instance of DataGenerator based only on first type parameter(A). It seems perfectly safe from compilation perspective:
if compiler finds DataGenerator for Int, only in one example, it will use it right away, if it finds several of them with different Bounds, just returns an error. This error I could possibly solve adding this parameter to implicit resolution. So what do you think?
Edit 1
Thanks to #Dmytro Mitin for solving it!
Looking further, I wanted to make an implementation for Array, so that if we want to summon an instance for an array we should have an instance for Array's parameter type, like this:
import scala.reflect.ClassTag
import scala.util.Random
trait PrimitiveGenerator[T] {
type Bounds
def generate(bounds: Bounds): T
def generatePossibly(bounds: Bounds): Option[T] = if (Random.nextDouble() < 0.5) None else Some(generate(bounds))
}
object PrimitiveGenerator {
type Aux[T, Bounds0] = PrimitiveGenerator[T] { type Bounds = Bounds0 }
def apply[A](implicit impl: PrimitiveGenerator[A]): Aux[A, impl.Bounds] = impl
}
object Generators {
implicit object IntGenerator extends PrimitiveGenerator[Int] {
override type Bounds = (Int, Int)
override def generate(bounds: (Int, Int) = (0, 1)): Int = Random.nextInt((bounds._2 - bounds._1) + 1) + bounds._1
}
implicit def toGenericArrayGenerator[A](implicit generator: PrimitiveGenerator[A],
classTag: ClassTag[A]): PrimitiveGenerator[Array[A]] = new PrimitiveGenerator[Array[A]] {
override type Bounds = ((Int, Int), generator.Bounds) //It means generate array of length from n to m where elements comply to Bounds of base generator
override def generate(bounds: Bounds): Array[A] = {
Array[A]()
}
}
}
object Test extends App {
import Generators._
println(PrimitiveGenerator[Int].generate((0, 42)))
PrimitiveGenerator[Array[Int]].generate((1 -> 10, 0 -> 42))
}
Now I am trying to create array generator dynamically and the Bounds are slightly changed depending on base generator bounds(by plan).
But something went wrong and now I have:
Error: type mismatch;
found : ((Int, Int), (Int, Int))
required: impl.Bounds
PrimitiveGenerator[Array[Int]].generate((1 -> 10, 0 -> 42))
How can it be resolved?
For example try
object PrimitiveGenerator {
def apply[A <: AnyVal] = new PartiallyApplied[A]
class PartiallyApplied[A <: AnyVal] {
def apply[B]()(implicit impl: PrimitiveGenerator[A, B]) = impl
}
}
object Test extends App {
import Generators._
PrimitiveGenerator[Int]().generate((0, 1))
}
or
object PrimitiveGenerator {
def generate[A <: AnyVal, B](b: B)(implicit impl: PrimitiveGenerator[A, B]) = impl.generate(b)
}
object Test extends App {
import Generators._
PrimitiveGenerator.generate((0, 1))
}
or
trait PrimitiveGenerator[T <: AnyVal] {
type Bounds
def generate(bounds: Bounds): T
def generatePossibly(bounds: Bounds): Option[T] = if (Random.nextDouble() < 0.5) None else Some(generate(bounds))
}
object PrimitiveGenerator {
type Aux[T <: AnyVal, Bounds0] = PrimitiveGenerator[T] { type Bounds = Bounds0 }
def apply[A <: AnyVal](implicit impl: PrimitiveGenerator[A]): Aux[A, impl.Bounds] = impl
}
object Generators {
implicit object IntGenerator extends PrimitiveGenerator[Int] {
override type Bounds = (Int, Int)
override def generate(bounds: (Int, Int) = (0, 1)): Int = Random.nextInt((bounds._2 - bounds._1) + 1) + bounds._1
}
}
object Test extends App {
import Generators._
PrimitiveGenerator[Int].generate((0, 1))
}
or
trait PrimitiveGenerator[T <: AnyVal] {
type Bounds = (T, T)
def generate(bounds: Bounds): T
def generatePossibly(bounds: Bounds): Option[T] = if (Random.nextDouble() < 0.5) None else Some(generate(bounds))
}
object PrimitiveGenerator {
def apply[A <: AnyVal](implicit impl: PrimitiveGenerator[A]): PrimitiveGenerator[A] = impl
}
object Generators {
implicit object IntGenerator extends PrimitiveGenerator[Int] {
override def generate(bounds: (Int, Int) = (0, 1)): Int = Random.nextInt((bounds._2 - bounds._1) + 1) + bounds._1
}
}
object Test extends App {
import Generators._
PrimitiveGenerator[Int].generate((0, 1))
}
I've recently started learning Scala's implicit "magic" and I'm having troubles with implicit Scala objects. I've tried all the possible variants but nothing seems to work.
Lets assume I have a class like this with some solve() function. It should return 2 Float values if the input a, b were Float. Otherwise it should return another type values:
class Solver[T](val a: T, val b: T) {
def solve[A](implicit num: customNumeric[T]): Option[(T, T)] = {
Option(
num.f(num.g(a)),
num.f(num.g(b)))
}
}
Let's assume another-type-value is an object of class like this:
class MyClass[T] (x: T, y: T)(implicit num: customNumeric[T]) {
val field : T = num.f(x)
}
And let's also assume that I dont have the functions I need in basic Scala Numeric so I should make my own custom numeric.
Here is what I've done:
I've made an abstract class for my own customNumeric with my methods f() and g() and couple of implicit objects that extend my customNumeric for some value types (Int, Float for example) and implemented method in them:
abstract class customNumeric[T] {
def f(x: T): T
def g(x: T): T
}
object customNumeric {
implicit object IntIsCustomNumeric extends customNumeric[MyClass[Int]] {
def f(x: MyClass[Int]) = new MyClass[Int](x.field + 5)
def g(x: MyClass[Int]) = new MyClass[Int](x.field - 5)
}
implicit object FloatIsCustomNumeric extends customNumeric[Float] {
def f(x: Float): Float = x + 3
def g(x: Float): Float = x - 3
}
}
In my opinion Solver's solve() should use implicit customNumeric object to get implementations for methods referenced inside solve() based upon type of the Solver's input values.
But this doesn't work as compiler says:
could not find implicit value for parameter num: customNumeric[Int]
def f...
It also complains because of not enough arguments for constructor MyClass at the same line.
I've already tried making companion object to cast Int to MyClass:
object Fraction {
implicit def int2MyClass(x: Int): MyClass[Int] = new MyClass[Int](x, 1)
}
But that also doen't seem to work. And I've tried to make another implicit object to implement methods I use in customNumeric[MyClass[Int]].
Do you have any ideas? Thanks in advance!
The problem is that you're trying to define the implicit objects with classes that themselves require that same implicit object.
Meaning, this:
class MyClass[T] (x: T, y: T)(implicit num: CustomNumeric[T])
Requires an existence of an implicit CustomNumeric[T]. You cannot define IntIsCustomNumeric using that type:
implicit object IntIsCustomNumeric extends customNumeric[MyClass[Int]]
When you implement IntIsCustomNumeric, you need to implement it for type Int, not for type MyClass[Int]. When you do that, i.e:
object CustomNumeric {
implicit object IntIsCustomNumeric extends CustomNumeric[Int] {
override def f(x: Int): Int = x
override def g(x: Int): Int = x
}
}
Now, you can create an Solver[Int] which takes an implicit CustomNumeric[Int]:
def main(args: Array[String]): Unit = {
import CustomNumeric._
val solver = new Solver[Int](1, 2)
println(solver.solve)
}
Now, it's also easier to create an implicit conversion from an Int type to something that creates a MyClass[Int]:
implicit object MyClassIsCustomNumeric extends CustomNumeric[MyClass[Int]] {
override def f(x: MyClass[Int]): MyClass[Int] = new MyClass[Int](x.field + 5)
override def g(x: MyClass[Int]): MyClass[Int] = new MyClass[Int](x.field + 3)
}
implicit def intToMyClass(i: Int) = new MyClass[Int](i)
What do you think about this
object customNumeric {
implicit object IntIsCustomNumeric extends customNumeric[Int] {
def f(x: Int): Int = x + 3
def g(x: Int): Int = x - 3
}
implicit object FloatIsCustomNumeric extends customNumeric[Float] {
def f(x: Float): Float = x + 3
def g(x: Float): Float = x - 3
}
implicit def int2MyClass(x: Int): MyClass[Int] = new MyClass[Int](x, 1)
implicit object cn extends customNumeric[MyClass[Int]] {
def f(x: MyClass[Int]) = x.field + 5
def g(x: MyClass[Int]) = x.field - 5
}
}
In my application I have multiple case classes and objects which are part of sealed trait hierarchy. I use them as messages in Akka.
Those classes need to be converted to user friendly form before sending through websocket.
Previously I used big pattern match to convert them in single place, but as number of types grows I would like to use implicit conversion:
object Types {
sealed trait Type
case object SubType1 extends Type
case object SubType2 extends Type
case object SubType3 extends Type
trait Converter[T] {
def convert(t: T): Int
}
}
object Implicits {
import Types._
implicit object Type1Coverter extends Converter[SubType1.type] {
override def convert(t: SubType1.type): Int = 1
}
implicit object Type2Coverter extends Converter[SubType2.type] {
override def convert(t: SubType2.type): Int = 2
}
implicit object Type3Coverter extends Converter[SubType3.type] {
override def convert(t: SubType3.type): Int = 3
}
}
object Conversion {
import Types._
def convert[T: Converter](t: T): Int = {
implicitly[Converter[T]].convert(t)
}
def convert2[T <: Type](t: T)(implicit ev1: Converter[SubType1.type], ev2: Converter[SubType2.type], ev3: Converter[SubType3.type]): Int = {
t match {
case t1#SubType1 =>
implicitly[Converter[SubType1.type]].convert(t1)
case t2#SubType2 =>
implicitly[Converter[SubType2.type]].convert(t2)
case t3#SubType3 =>
implicitly[Converter[SubType3.type]].convert(t3)
}
}
}
I would like to use them as follow:
import Types._
import Conversion._
import Implicits._
val t1 = SubType1
val x1: Int = convert(t1)
val t: Type = SubType2 // T is of type Type
//Is it possible to handle that?
//val x: Int = convert(t)
val y: Int = convert2(t)
I would love to know if there is any "magic" way to generate something like convert2 automatically without writing a macro. Maybe there is already a library which provides macro like this?
Since you have no info at compile time about t's type, you have to work at runtime.
if you put your Converters in a sealed family, you could do something like the follwing, using a technique explained in this question:
import shapeless._
trait AllSingletons[A, C <: Coproduct] {
def values: List[A]
}
object AllSingletons {
implicit def cnilSingletons[A]: AllSingletons[A, CNil] =
new AllSingletons[A, CNil] {
def values = Nil
}
implicit def coproductSingletons[A, H <: A, T <: Coproduct](implicit
tsc: AllSingletons[A, T],
witness: Witness.Aux[H]): AllSingletons[A, H :+: T] =
new AllSingletons[A, H :+: T] {
def values = witness.value :: tsc.values
}
}
trait EnumerableAdt[A] {
def values: Set[A]
}
object EnumerableAdt {
implicit def fromAllSingletons[A, C <: Coproduct](implicit
gen: Generic.Aux[A, C],
singletons: AllSingletons[A, C]): EnumerableAdt[A] =
new EnumerableAdt[A] {
def values = singletons.values.toSet
}
}
object Types {
sealed trait Type
case object SubType1 extends Type
case object SubType2 extends Type
case object SubType3 extends Type
sealed abstract class Converter[T <: Type: ClassTag] {
def convert(t: T): Int
def convertibleObjectClass = implicitly[ClassTag[T]].runtimeClass
}
object Implicits {
implicit object Type1Converter extends Converter[SubType1.type] {
override def convert(t: SubType1.type): Int = 1
}
implicit object Type2Converter extends Converter[SubType2.type] {
override def convert(t: SubType2.type): Int = 2
}
// let's pretend you FORGOT to add Type3Converter
// implicit object Type3Converter extends Converter[SubType3.type] {
// override def convert(t: SubType3.type): Int = 3
// }
}
}
object Conversion {
import Types._
val AllConverters: Map[Class[_], Converter[_ <: Type]] = implicitly[EnumerableAdt[Converter[_ <: Type]]].values
.map(c => c.convertibleObjectClass -> c).toMap
// You're sure you have all the converters here but you can't be sure you remembered to add one per subtype... you have to test it
// you are sure this cast doesn't fail anyway because of how you created the map
def findConverter[T <: Type](t: T) = AllConverters.get(t.getClass).asInstanceOf[Option[Converter[T]]]
def convert2[T <: Type](t: T): Option[Int] = findConverter(t).map(_.convert(t))
}
object Test extends App {
import Types._
import Conversion._
val t: Type = SubType2
val t2: Type = SubType3
// works, because a Converter[Subtype2.type] exists
val a: Option[Int] = convert2(t)
// returns None, because a Converter[Subtype3.type] doesn't exist
val b: Option[Int] = convert2(t2)
}
Here's a very simple example:
scala> class A(x: Int) {
| def withX(newX: Int): A = new A(newX)
| override def toString = x.toString
| }
defined class A
scala> class B(x: Int) extends A(x) {
| override def withX(newX: Int): B = new B(newX)
| }
defined class B
So we have two classes:
A, which defines a method withX returning the object of type A, and
B, which extends A and overrides its withX method to return the object of type B.
Now I'd like to create a container, which can process instances of both A and B. It should have a method, which can accept an instance of A (or B), run withX on it and return another instance of A (or B). To be more specific, the exact functionality I want to achieve (note the return types):
scala> val a = new A(0)
a: A = 0
scala> val b = new B(0)
b: B = 0
scala> val testA = new Test[A]
testA: Test[A] = Test#4bf59a3d
scala> val testB = new Test[B]
testB: Test[B] = Test#65e565d1
scala> testA.test(a)
res1: A = 1
scala> testB.test(b)
res2: B = 1
I suppose that this can be achieved via class with upper-bounded type parameter. I've tried to do it like this, but got an error:
scala> class Test[T <: A] {
| def test(t: T): T = t withX 1
| }
<console>:9: error: type mismatch;
found : A
required: T
def test(t: T): T = t withX 1
^
The only workaround I managed to find looks somewhat ugly. Besides that, the match clause will need to be rewritten if we add some new class C extends B:
scala> class Test[T <: A] {
| def test(t: T): T = (t match {
| case b: B => b withX 1
| case a: A => a withX 1
| }).asInstanceOf[T]
| }
Can this functionality be achieved in more elegant way? I feel like I'm missing something about type parameters, type bounds and all scala type system in general.
While it's possible to override a method with a more specific return type, it's rarely a good idea. Consider the following:
class C(x: Int) extends A(x) {
override def withX(newX: Int): B = new B(x)
}
This is completely legal, but breaks your assumption that the return type of withX is the same subtype of A as the (statically known) type of the instance you're calling it on.
You can make that assumption safely (i.e. with support from the type system) by using F-bounded polymorphism:
trait Base[T <: Base[T]] {
def withX(newX: Int): T
}
class A(x: Int) extends Base[A] {
def withX(newX: Int) = new A(newX)
override def toString = x.toString
}
class B(x: Int) extends Base[B] {
def withX(newX: Int) = new B(newX)
override def toString = x.toString
}
class Test[T <: Base[T]] {
def test(t: T): T = t withX 1
}
This requires some changes to your type hierarchy, but it's a pretty standard way to encode the idea that the return type of a method is the same as the instance it's called on.
Somewhat along the lines of Travis' answer, if you want to encode the fact that a type supports a specific operation (withX in this case), you can consider using a type class.
class A(x: Int) {
override def toString = x.toString
}
class B(x: Int) extends A(x)
trait HasWithX[T] {
def withX(x: Int): T
}
implicit val AHasWithX = new HasWithX[A] {
def withX(x: Int) = new A(x)
}
implicit val BHasWithX = new HasWithX[B] {
def withX(x: Int) = new B(x)
}
class Test[T] {
def test(t: T)(implicit ev: HasWithX[T]): T = ev withX 1
}
Example:
scala> val a = new A(0)
a: A = 0
scala> val b = new B(0)
b: B = 0
scala> val testA = new Test[A]
testA: Test[A] = Test#4bf59a3d
scala> val testB = new Test[B]
testB: Test[B] = Test#65e565d1
scala> testA.test(a)
res1: A = 1
scala> testB.test(b)
res2: B = 1