Reputation: 15103
case class Cat(name: String)
object CuterImplicits {
implicit class CatCuteChecker(c: Cat) {
def isCute(c: Cat) = true
}
}
trait CuteChecker[A] {
def isCute(a: A): Boolean
}
object CheckingForCuteness {
def isItCute[A](a: A) = implicitly[CuteChecker[A]].isCute(a)
}
object Main extends App {
CheckingForCuteness.isItCute[Cat](Cat("funny"))
}
how to fix:
Error:(17, 37) could not find implicit value for parameter e: CuteChecker[A] def isItCute[A](a: A) = implicitly[CuteChecker[A]].isCute(a) ^
Upvotes: 11
Views: 18159
Reputation: 8203
Implicits have to be visible unqualified at the point of invocation. Different ways that implicits can become visible is best described in this answer: https://stackoverflow.com/a/5598107/843348.
It is also not completely clear what you are trying to achieve and there are a number of possible ways to achieve something like the example.
One possibility is monkey patching Cat using an implicit class:
case class Cat(name: String)
object CuteImplicits {
implicit class CuteCat(c: Cat){
def isCute = true
}
}
object Main extends App {
import CuteImplicits._
Cat("funny").isCute
}
You put implicits in the companion object of an associated type and the it is visible automatically.
case class Cat(name: String)
object Cat {
implicit class CuteCat(c: Cat){
def isCute = true
}
}
object Main extends App {
Cat("funny").isCute
}
In minimal example like this it not clear why you would not build the functionality directly into Cat
.
Upvotes: 0
Reputation: 67280
If you use implicitly
that simply makes a value implicitly in scope "explicitly" available. So your isItCute
method should be either of the following two variants:
def isItCute[A: CuteChecker](a: A) = implicitly[CuteChecker[A]].isCute(a)
def isItCute[A](a: A)(implicit cc: CuteChecker[A]) = cc.isCute(a)
Next you want an implicit instance for Cat
. The implicit class
doesn't help you here because it requires a non-implicit value of type Cat
. You can see that this approach is wrong because the constructor parameter is never used. You can use an implicit object
:
implicit object CatCuteChecker extends CuteChecker[Cat] {
def isCute(c: Cat) = true
}
Finally, you provide implicits in object CuterImplicits
. For them to be visible to Main
, you need to import the contents:
object Main extends App {
import CuterImplicits._
CheckingForCuteness.isItCute[Cat](Cat("funny"))
}
Upvotes: 10
Reputation: 11882
There a multiple problems in your situation. The implicitly
call expects an instance of the CuteChecker
trait, while CatCuteChecker
is neither an instance nor does not it extend this trait. Furthermore, the c
class parameter is completely unnecessary.
You can fix your problem by declaring that subtyping relationship and providing an implicit
value:
object CuterImplicits
{
class CatCuteChecker with CuteChecker
{
def isCute(c: Cat) = true
}
implicit val catCuteChecker = new CatCuteChecker
}
Upvotes: 0