Given a made-up F type-class:
scala> trait F[A] {}
defined trait F
and this definition, which uses a context bound to require that the input A has a type-class instance of F:
scala> def f[A : F](x: A) = ???
f: [A](x: A)(implicit evidence$1: F[A])Nothing
I defined a Person and type-class instance:
scala> case class Person(name: String)
defined class Person
scala> implicit val person: F[Person] = new F[Person] {}
person: F[Person] = $anon$1#262b2c86
And the following compiles:
scala> f(Person("foo"))
scala.NotImplementedError: an implementation is missing
But, there's no String implementation, so it fails.
scala> f("foobar")
<console>:17: error: could not find implicit value for evidence parameter of type F[String]
f("foobar")
^
I then defined an F[String] using:
scala> implicit def fInstance(x: String) = new F[String] {}
fInstance: (x: String)F[String]
But, I can't run:
scala> f("foobar")
<console>:18: error: could not find implicit value for evidence parameter of type F[String]
f("foobar")
^
since I do not have an implicit F[String], but rather a String => F[String].
What's the proper way to use such an implicit def to meet the F[String] constraint, i.e. call the f function successfully with a type of String?
I got it to work via:
scala> implicit val x: F[String] = implicitly[String => F[String]].apply("foobar")
x: F[String] = $anon$1#7b7fdc8
scala> f("foobar")
scala.NotImplementedError: an implementation is missing
at scala.Predef$.$qmark$qmark$qmark(Predef.scala:230)
at .f(<console>:12)
... 33 elided
But I'm not sure if it's the right/clean way to do it.
You defined an implicit conversion. If you want to use a def to provide typeclass instances you just write the same as you'd write an implicit val but replace val with def.
implicit def fInstance = new F[String] {}
Normally you only use a def if you need type parameters, like here.
implicit def fInstance[A] = new F[List[A]] {}
Or
implicit def fInstance[A](implicit ev: F[A]) = new F[List[A]] {}
Your fInstance defines an implicit conversion, i.e. a way to turn a String into F[String]. For generating a typeclass instance, a method accepting implicit parameters can be used:
implicit def fInstance(implicit x: String) = new F[String] {}
it is typically used in FP libraries to derive one typeclass from another:
implicit def optionMonoid[A](implicit S: Semigroup[A]): Monoid[Option[A]] = ???
// or, which is the same
// implicit def optionMonoid[A: Semigroup]: Monoid[Option[A]] = ???
The idea is that F[String] can operate on any String in general, not being dependent on actual arguments provided into function. Of course, you can always provide instances explicitly:
f("foobar")(new F[String] { })
As a follow-up, the important part of typeclasses is that you can define them ad-hoc, i.e. not having access to definitions of F and String at all, and you are forced to scope implicits in Scala and import them, so it's totally ok.
Here is a simpler version of your definition (and you can remove implicit from fInstance):
implicit val singleFInstance: F[String] = fInstance("") // or fInstance("foobar"), etc.
Whether this is the right thing to do, very much depends on what F and f are supposed to mean.
But generally speaking: if F is really a type-class, fInstance(string) gives different results depending on the string (not just different instances, but different behavior), and f's signature is correct, then this is wrong and you should accept that calling f("foobar") isn't meaningful.
Related
I'm trying to describe the types which a case class contains.
import shapeless._
import shapeless.ops.hlist.LiftAll
trait Desc[T] {
def description: String
}
case class Foo(f: Int)
object Foo {
implicit val description: Desc[Foo] = new Desc[Foo] { val description = "foo" }
}
case class SomeCaseClass(f: Foo)
val gen = Generic[SomeCaseClass]
val lifted = implicitly[LiftAll[Desc, gen.Repr]].instances.toList
Gives me
could not find implicit value for parameter toTraversableAux: shapeless.ops.hlist.ToTraversable.Aux[shapeless.ops.hlist.LiftAll[Playground.this.Desc,Playground.this.gen.Repr]#Out,List,Lub]
not enough arguments for method toList: (implicit toTraversableAux: shapeless.ops.hlist.ToTraversable.Aux[shapeless.ops.hlist.LiftAll[Playground.this.Desc,Playground.this.gen.Repr]#Out,List,Lub])toTraversableAux.Out.
Unspecified value parameter toTraversableAux.
Scastie here: https://scastie.scala-lang.org/bXu71pMQQzCqrrsahVBkWA
When you summon an implicit instance with implicitly[LiftAll[Desc, gen.Repr]] then the dependent type Out of LiftAll is lost, so the compiler doesn't know which type exactly instances will return.
To work around this problem most typeclasses in Shapeless define an apply method in their companion object which does retain all dependent type information. It's the reason that you can use gen.Repr in a meaningful way after calling val gen = Generic[SomeCaseClass]. For some reason however LiftAll.apply was not implemented in this way. So that leaves you the option of implementing your own implicitly, or since you're using Shapeless anyway, use its the which is supposed to be a better implicitly.
scala> def impl[T <: AnyRef](implicit ev: T): ev.type = ev
impl: [T <: AnyRef](implicit ev: T)ev.type
scala> impl[LiftAll[Desc, gen.Repr]].instances.toList
res1: List[Desc[Foo]] = List(Foo$$anon$1#40b3708a)
scala> the[LiftAll[Desc, gen.Repr]].instances.toList
res2: List[Desc[Foo]] = List(Foo$$anon$1#40b3708a)
You can see the difference here in the inferred types that the REPL displays:
scala> impl[LiftAll[Desc, gen.Repr]]
res3: LiftAll.Aux[Desc,Foo :: HNil,Desc[Foo] :: HNil] = shapeless.ops.hlist$LiftAll$$anon$206#384d060c
scala> implicitly[LiftAll[Desc, gen.Repr]]
res4: LiftAll[Desc,gen.Repr] = shapeless.ops.hlist$LiftAll$$anon$206#30787774
with Cats, I can write this simple program
def foo(x: Int) = x + 1
val bar = Functor[Future](foo)
and Now I can do a bar(future(1)) and get a Future.Success(2) as a result. Very good.
But suppose my function was
def foo[T](x: T)(implicit m: Manifest[T]) : String = {...}
Now if I try to lift this function
def futureFoo = Functor[Future].lift(foo)
I get a compiler error No Manifest available for T.
So how do I lift this function?
I searched and found this thread (which is for scalaz)
Lifting a function which takes implicit parameter using functor (Scalaz7)
But I still couldn't create anything which worked for me. I tried
val futureFoo = Functor[T].lift2(foo[T] _)
but this doesn't compile
Functions in Scala cannot have implicit parameters, so when you try to eta-expand a method with an implicit parameter into a function, the implicit needs to be resolved before the function itself is applied. That is, at the time of eta-expansion. The compiler doesn't have a generic Manifest[T] in scope, but futureFoo can require one.
def foo[T](x: T)(implicit m: Manifest[T]) : String = ""
scala> def optionFoo[T: Manifest] = Functor[Option].lift(foo[T] _)
optionFoo: [T](implicit evidence$1: Manifest[T])Option[T] => Option[String]
I used Option because I didn't have a Functor[Future] readily available, the the same concept applies. Note that in order to use this, you'll need to supply the type parameter manually for it to return the correct function.
scala> optionFoo[Int].apply(Option(1))
res2: Option[String] = Some()
Consider the following REPL session:
# def test[C[X] <: TraversableOnce[X]](implicit cbf: CanBuildFrom[C[Int], Int, C[Int]]) = cbf()
defined function test
# test[List]
res32: collection.mutable.Builder[Int, List[Int]] = ListBuffer()
# def test[C[X] <: TraversableOnce[X]] = implicitly[CanBuildFrom[C[Int], Int, C[Int]]]
cmd33.sc:1: Cannot construct a collection of type C[Int] with elements of type Int based on a collection of type C[Int].
def test[C[X] <: TraversableOnce[X]] = implicitly[CanBuildFrom[C[Int], Int, C[Int]]]
^
Compilation Failed
The first definition of test function compiles and works, while the second one doesn't compile. The only difference between them is the way how the instance of CanBuildFrom is obtained. In first case it's declared as implicit parameter, requiring the compiler to find one. In second case it's invoked via implicitly function, which, in theory, should behave the same in terms of implicit search scope. What causes this behavior?
The definition of implicitly (in Predef) is:
def implicitly[A](implicit ev: A): A = A
It simply makes explicit to you an implicit already in scope (at the use site).
Now when you write this:
import collection.generic.CanBuildFrom
def test[C[X] <: TraversableOnce[X]]
(implicit cbf: CanBuildFrom[C[Int], Int, C[Int]]) = ???
You are asking the caller to provide an implicit (at the call site).
When you write
def test[C[X] <: TraversableOnce[X]] =
implicitly[CanBuildFrom[C[Int], Int, C[Int]]]
You are asking the compiler with the call implicitly to look-up an implicit already in scope. But you are not having any implicit of the given type in scope! So the two definitions of test are doing something entirely different.
You use implicitly normally to get hold of an implicit to which you don't have the name, because it was specified using the context-bounds or type-class notation, like def test[A: TypeClass]. You cannot use that notation here because CanBuildFrom has three type parameters and not one. So you cannot do much with implicitly here.
You could use implicitly with your first case:
def test[C[X] <: TraversableOnce[X]]
(implicit cbf: CanBuildFrom[C[Int], Int, C[Int]]) = {
implicit val onceAgain = implicitly[CanBuildFrom[C[Int], Int, C[Int]]]
assert(onceAgain == cbf)
}
But then you already know that you have that implicit with name cbf...
Note that you can get hold of an implicit CanBuildFrom for a known collection type:
implicitly[CanBuildFrom[List[Int], Int, List[Int]]] // works!
But this doesn't work if your collection type (C[X]) is abstract.
Given:
scala> trait Resource[A] { def f: String }
defined trait Resource
scala> case class Foo(x: String)
defined class Foo
And then an implicit:
scala> implicit def fooToResource(foo: Foo): Resource[Foo] =
new Resource[Foo] { def f = foo.x }
The following works:
scala> implicitly[Resource[Foo]](Foo("foo")).f
res2: String = foo
I defined a function:
scala> def f[A](x: A)(implicit ev: Resource[A]): String = ev.f
f: [A](x: A)(implicit ev: Resource[A])String
However, the following code fails to compile:
scala> f(Foo("foo"))
<console>:17: error: could not find implicit value for parameter ev: Resource[Foo]
f(Foo("foo"))
Secondly, then I tried:
scala> f2(Foo("bippy"))
<console>:17: error: could not find implicit value for parameter ev: Resource[Foo]
f2(Foo("bippy"))
^
Lastly, I attempted:
scala> def g(foo: Foo)(implicit ev: Resource[Foo]): String = ev.f
g: (foo: Foo)(implicit ev: Resource[Foo])String
scala> g(Foo("5"))
<console>:17: error: could not find implicit value for parameter ev: Resource[Foo]
g(Foo("5"))
^
However, it failed too. How can I fix f?
Ok with Peter Neyens' answer, this is not a typeclass, this is an implicit conversion, which you should avoid - there should have been some warning, asking that you import scala.language.implicitConversions.
As a complement, here is why the first implicitly works:
Implicitly is just:
def implicitly[T](implicit ev: T): T = e
When you write implicitly[T] without supplying a parameter, it will look for an implicit of type T in scope and return it. However, you call implicitly with a parameter (I believe there is no legitimate reason to do that, ever), so it would just return your parameter, Foo("foo"), an instance of Foo. Except that you explicitly stated that T should be Resource[Foo]. If you had written a type ascription, such as (Foo("foo"): Resource[Foo]), it would have worked the same way. implicitly is not relevant here.
The point is that Foo("foo") is not of the expected type Resource[Foo], but just a Foo. The compiler would reject that, except that at this point, the implicit conversion you defined above kicks in, and your Foo instance is transformed into a Resource[Foo]. Then, you can call f.
Next, you call your f(Foo("foo")). There is an implicit parameter, however this time, you don't supply it. So the compiler looks for one (while it did no such thing the first time), and as there is no such instance, fails.
The implicit def fooToResource is not a type class instance, but does return one if you supply a Foo, that's the reason the following line works :
implicitly[Resource[Foo]](Foo("foo")).f
A solution would be to change the Resource.f function to take a parameter of type A :
trait Resource[A] {
def f(a: A): String
}
You then could define a Resource type class instance for Foo as follows:
case class Foo(x: String)
implicit val fooResource = new Resource[Foo] {
def f(foo: Foo) = foo.x
}
We can rewrite f to use the changed Resource :
def f[A](a: A)(implicit resA: Resource[A]): String = resA.f(a)
Which does what (I think) you need :
f(Foo("hello world")) // String = hello world
Is there a way to make this work? (Scala 2.8.1)
class A
def f(implicit a: A) = 0
class Vendor[T](val v: T)
implicit val vendor = new Vendor(new A)
implicit def vendorToVal[T](implicit v: Vendor[T]) = v.v
f
The error is: 'diverging implicit expansion for type A starting with method vendorToVal'
This is related to Lift 2.2 dependency injection, the real code looks like this:
class UserStore(implicit db: DbAccess)
object DependencyFactory extends Factory {
implicit val db = new FactoryMaker[DbAccess](Model) {}
import db._ // implicit conversion would allow to remove this import
implicit val userStore = new FactoryMaker[UserStore](new UserStore) {}
}
This question is related to: Is there a way to implicitly convert an implicit parameter in Scala?
The problem is caused with vendorToVal method - I observed the same behavior many times, when I've been using implicit parameters in implicit type-parametrized methods. Unfortunately, I've found no simple and elegant glue in 2.8._.
Some interesting threads, related to the topic:
http://scala-programming-language.1934581.n4.nabble.com/scala-Why-is-this-a-diverging-implicit-td1998156.html
http://www.scala-lang.org/node/6847
In Scala 2.9 trunk, you can do this:
scala> class A
defined class A
scala> def f(implicit a: A) = 0
f: (implicit a: A)Int
scala>
scala> class Vendor[T](val v: T)
defined class Vendor
scala> implicit def value[T: Vendor] = implicitly[Vendor[T]].v
value: [T](implicit evidence$1: Vendor[T])T
scala> implicit val vendor = new Vendor(new A)
vendor: Vendor[A] = Vendor#bbb2d0
scala> f
res0: Int = 0
Calling f will search for a value of type A, and find the implicit value[A], which requires an evidence parameter of type Vendor[A]. It resolves this evidence parameter to vendor.
I don't think implicits were that powerful in 2.8.1.