I have the following scala code. I don't understand why the implicit is not being figured by the compiler. I also tried putting the import line inside Main. Note however that when the implicit object was created inside Main, then the code ran correctly
import LoggingAddon._
object Main {
def main(args: Array[String]): Unit = {
val dog = new Dog
Util.act(dog)
}
}
class Dog {
def bark(): Unit = {
println("woof")
}
}
trait Action[A] {
def action(x: A): Unit
}
trait WithoutLogging[A] extends Action[A] {
}
trait WithLogging[A] extends Action[A] {
}
object LoggingAddon {
implicit object DogWithLogging extends WithLogging[Dog] {
override def action(x: Dog): Unit = {
println("before")
x.bark()
print("after")
}
}
}
object NoLoggingAddion {
implicit object DogWithoutLogging extends WithoutLogging[Dog] {
override def action(x: Dog): Unit = {
x.bark()
}
}
}
object Util {
def act(x: Dog)(implicit nolog: Action[Dog]): Unit = {
nolog.action(x)
}
}
I have imported the necessary implicit from the LoggingAddon but still the scala compiler says could not find implicit Action[Dog]
All I'm trying to do is make a pluggable typeclass. Rather than changing any piece of code, merely change the import statements to have different side effects
Simply move the order of usage where implicit is imported, I moved to the bottom in following example
class Dog {
def bark(): Unit = {
println("woof")
}
}
trait Action[A] {
def action(x: A): Unit
}
trait WithoutLogging[A] extends Action[A] {
}
trait WithLogging[A] extends Action[A] {
}
object LoggingAddon {
implicit object DogWithLogging extends WithLogging[Dog] {
override def action(x: Dog): Unit = {
println("before")
x.bark()
print("after")
}
}
}
object NoLoggingAddion {
implicit object DogWithoutLogging extends WithoutLogging[Dog] {
override def action(x: Dog): Unit = {
x.bark()
}
}
}
object Util {
def act(x: Dog)(implicit nolog: Action[Dog]): Unit = {
nolog.action(x)
}
}
import LoggingAddon._
object Main {
def main(args: Array[String]): Unit = {
val dog = new Dog
Util.act(dog)
}
}
Related
Suppose I have a trait defined like
trait SomeTrait[A] {
def doSomething(): Seq[A]
}
and multiple classes that extend this trait as follows.
class SomeClass extends SomeTrait[SomeType] {
def doSomething(): Seq[SomeType] = {
:
}
}
Now in another class, I want to store the collection of instances of the classes extending the trait.
class AnotherClass {
pirvate val someClassInstances = mutable.Buffer[SomeTrait[_]]()
def addSomeClass[A](sc: SomeTrait[A]): Unit = {
this.someClassInstances += sc
}
}
How can I avoid using the existential type here?
Does the following meet your needs:
import scala.collection.mutable
trait SomeTrait[A] {
def doSomething(): Seq[A]
}
class SomeClass extends SomeTrait[Int] {
def doSomething(): Seq[Int] = ???
}
class AnotherClass {
private val someClassInstances = mutable.Buffer[SomeTrait[_]]()
def addSomeClass(sc: SomeTrait[_]): Unit = {
this.someClassInstances += sc
}
}
?
I have tried solutions, described in How to override an implicit value?, but it does not help. Here is a code example.
A definition of TestImplicit abstraction with 2 different implementations (analogue of ExecutionContextExecutor):
trait TestImplicit {
def f(s:String):Unit
}
object TestImplicitImpl1 extends TestImplicit {
override def f(s: String): Unit = println(s"1: $s")
}
object TestImplicitImpl2 extends TestImplicit {
override def f(s: String): Unit = println(s"2: $s")
}
And in the ImplDefinition object a q variable is defined to be used implicitly via import (analogue of ExecutionContext.Implicits.global):
object ImplDefinition {
implicit val q:TestImplicit = TestImplicitImpl1
}
Client that defines a method, accepting TestImplicit implicitly (analogue of scala.concurrent.Future):
trait TestImplicitClient {
def fu(implicit ti:TestImplicit):Unit
}
object TestImplicitClient extends TestImplicitClient {
override def fu(implicit ti: TestImplicit): Unit = {
println("client")
ti.f("param")
}
}
The next step, a client of client, that chooses which implementation of TestImplicit should be used, the decision is done via import (analogue of API that uses Future):
object ClientOfClient {
import somepackage.ImplDefinition.q
def t():Unit =
TestImplicitClient.fu
}
Now in test, I want to use this ClientOfClient.t(), but I need to override implicit, and use TestImplicitImpl2 instead. The main idea behind - implicits should be defined/overridable by the client of API, but not by API itself:
import somepackage.{ClientOfClient, TestImplicit, TestImplicitImpl2}
import org.junit.Test
class ImplTest {
// trying to hide it via import, does not help
import somepackage.ImplDefinition.{q => _,_}
#Test def test(): Unit ={
//trying to hide it via downgrading to non-implicit, does not work either
val q = somepackage.ImplDefinition.q
implicit val ti = TestImplicitImpl2
ClientOfClient.t()
}
}
Each time I run test, I get in the output:
client
1: param
But not expected:
client
2: param
How can I fix it? I need a way to allow clients to override implicits and stay with as simple API as possible. Which means, I do not want to add additional implicit parameter into ClientOfClient.t() method.
As soon as you have a singleton object ClientOfClient with a hard-coded constant TestImplicitImpl1 everywhere, there is essentially nothing you can do. But there are several work-arounds.
1. Use default implicit parameters
object ClientOfClient {
def t()(implicit ti: TestImplicit = ImplDefinition.q): Unit =
TestImplicitClient.fu
}
object ImplTest {
def test(): Unit = {
implicit val ti2 = TestImplicitImpl2
ClientOfClient.t()
}
}
ImplTest.test() // 2: param
2. Supply the implicit through a separate method that can be overridden
If you want to make the implicit overridable, then make ClientOfClient extendable, and create a method (here "cocti") that returns the implicit, instead of importing the implicit directly. You can then override the method (whereas you cannot override an import).
This here produces 2: param in the end of the day:
trait TestImplicit {
def f(s: String): Unit
}
object TestImplicitImpl1 extends TestImplicit {
override def f(s: String): Unit = println(s"1: $s")
}
object TestImplicitImpl2 extends TestImplicit {
override def f(s: String): Unit = println(s"2: $s")
}
object ImplDefinition {
implicit val q: TestImplicit = TestImplicitImpl1
}
trait TestImplicitClient {
def fu(implicit ti: TestImplicit): Unit
}
object TestImplicitClient extends TestImplicitClient {
override def fu(implicit ti: TestImplicit): Unit = {
println("client")
ti.f("param")
}
}
class ClientOfClient {
implicit def cocti: TestImplicit = {
ImplDefinition.q
}
def t():Unit =
TestImplicitClient.fu
}
object ImplTest {
def test(): Unit = {
implicit val ti2 = TestImplicitImpl2
new ClientOfClient {
override def cocti = ti2
}.t()
}
}
ImplTest.test() // 2: param
So I have defined a Scala object using the following code:
trait SomeTrait {
def someMethod(): Unit
}
package somepackage1 {
object Impl1 extends SomeTrait {
def someMethod(): Unit = { }
}
object Impl2 extends SomeTrait {
def someMethod(): Unit = { }
}
}
I want to access the object given its fully qualified name i.e. somepackage1.Impl2. A method something like following:
package object somewhereElse {
def getImpl(qualifiedName: String): SomeTrait = {
???
}
}
What should be the code as part of getImpl method?
Here is a solution that uses the Java Reflection API (you might want to use the newer Scala Reflection API instead):
trait SomeTrait {
def someMethod(): Unit
}
package somepackage1 {
object Impl1 extends SomeTrait {
def someMethod(): Unit = { println("impl 1") }
}
object Impl2 extends SomeTrait {
def someMethod(): Unit = { println("impl 2") }
}
}
package object somewhereElse {
def getImpl(qualifiedName: String): SomeTrait = {
val clazz = Class.forName(qualifiedName + "$")
clazz
.getField("MODULE$")
.get(clazz)
.asInstanceOf[SomeTrait]
}
}
object Demo {
def main(args: Array[String]): Unit = {
somewhereElse.getImpl("somepackage1.Impl2").someMethod()
}
}
It's quite similar to Dima's comment above, with two minor differences: note the '$' appended to class name, and also the .get(clazz) instead of just .get() (without the clazz, it throws java.lang.NoSuchFieldException: MODULE$).
When saved to file f.scala, and compiled and invoked using
scalac f.scala && scala Demo
it prints:
impl 2
I am trying to create a type class in Scala and use it to make a simple polymorphic case class. This example doesn't compile and gives "could not find implicit value for parameter writer:A$A228.this.ValueWriter[T]". I can't really figure out what could be going wrong or where to start.
trait Keeper
case class StringKeeper(measure: String) extends Keeper
case class StringLengthKeeper(measure: Int) extends Keeper
trait ValueWriter[A] {
def write(value: String): A
}
object DefaultValueWriters {
implicit val stringWriter = new ValueWriter[StringKeeper] {
def write(value: String) = StringKeeper(value)
}
implicit val stringLengthWriter = new ValueWriter[StringLengthKeeper] {
def write(value: String) = StringLengthKeeper(value.length)
}
}
object Write {
def toWrite[A](value: String)(implicit writer: ValueWriter[A]) = {
writer.write(value)
}
}
case class WriterOfKeepers[T <: Keeper](value: String) {
def run: T = {
Write.toWrite[T](value)
}
}
import DefaultValueWriters._
val writerLengthKeeper = WriterOfKeepers[StringLengthKeeper]("TestString")
writerLengthKeeper.run
There is no implicit ValueWriter in scope when you call Write.toWrite.
You need to have the implicit parameter in the constructor
case class WriterOfKeepers[T <: Keeper : ValueWriter](value: String) {
def run: T = {
Write.toWrite[T](value)
}
}
or in the method
case class WriterOfKeepers[T <: Keeper](value: String) {
def run(implicit writer: ValueWriter[T]): T = {
Write.toWrite(value)
}
}
or find some other way compatible with your requirements (and I don't know those).
I am trying to write a macro that extracts the type information. Here is a minimized version.
class Extractor[E] {
def extract(entity: E): Unit = macro ExtractorImpl.extractImpl[E]
}
object ExtractorImpl {
def extractImpl[E: c.WeakTypeTag](c: Context)(entity: c.Expr[E]): c.Tree = {
import c.universe._
val actualType = implicitly[WeakTypeTag[E]].tpe
c.info(c.enclosingPosition, actualType.toString, true)
q"{}"
}
}
Here is a typical implementation of Extractor:
case class Person(name: String)
object PersonExtractor extends Extractor[Person]
If I use this class directly as in PersonExtractor.extract(new Person("test name")), I get Person printed as info. But, if I use it indirectly as follows, it prints only E:
class Mapper[E](extractor: Extractor[E]) {
def extract(e: E) = extractor.extract(e)
}
class PersonMapper extends Mapper[Person](new Extractor[Person])
class Test {
new PersonMapper().extract(new Person("test name"))
}
How do I go about getting the Person type available as actualType?
use implicit macro
trait Extractor[E] {
def extract(entity: E): Unit
}
object Extractor {
implicit def i[E] : Extractor[E] = macro ExtractorImpl.extractImpl[E]
}
object ExtractorImpl {
def extractImpl[E: c.WeakTypeTag](c: Context):c.Tree = {
import c.universe._
val actualType = c.weakTypeOf[E]
c.info(c.enclosingPosition, actualType.toString, false)
q"""
new Extractor[$actualType]{
def extract(entity: $actualType): Unit = println("hello world")
}
"""
}
}
// test
case class Person(name: String)
//object PersonExtractor extends Extractor[Person]
class Mapper[E] {
def extract(e: E)(implicit extractor: Extractor[E]) = extractor.extract(e)
}
class PersonMapper extends Mapper[Person]
class Test {
new PersonMapper().extract(new Person("test name")) // show info:Person
}
Edit:
//test2
class Mapper2[E](extractor: Extractor[E]) {
def extract(e: E) = extractor.extract(e)
}
object Mapper2 extends Mapper2[Person](Extractor.i[Person])//also show info:Person