ffff
ffff

Reputation: 3070

Scala: Not able to find implicit from object

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

Upvotes: 0

Views: 250

Answers (1)

prayagupadhyay
prayagupadhyay

Reputation: 31252

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

Upvotes: 2

Related Questions