CanBuildFrom not found when invoked implicitly - scala

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.

Related

Using `implicit def`

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.

Calling method with an implicit parameter

I have the following method:
def test[T](implicit ev: T <:< Int, t : T) = println(t)
How can I call it? I tried
test(10)
But the compiler prints out the following error:
Error:(19, 9) not enough arguments for method test: (implicit ev: <:<[T,Int], implicit t: T)Unit.
Unspecified value parameter t.
test(10)
^
First of all, I thought that we could just omit implicit parameters and specify only explicit ones. And secondly, why does it's saying that that the parameter t is implicit?
implicit t: T
How does it actually work?
First of all, I thought that we could just omit implicit parameters and specify only explicit ones.
You either specify all the implicits in the list, or you don't specify them at all. According to the specification, if one parameter is marked as implicit, the entire argument list is marked as well:
An implicit parameter list (implicit p1, ……, pn) of a method marks the parameters p1, …, pn as implicit.
secondly, why does it's saying that that the parameter t is implicit?
Because of what was answered in your first part.
If you still want to invoke it like that, you can use implicitly:
test(implicitly, 10)
Generally, it is recommended that you require an implicit in a separate argument list:
def test[T](i: Int)(implicit ev: T <:< Int) = println(t)
the problem is that the implicit parameter should be in its own list, like this:
def test[T](t : T)(implicit ev: T <:< Int) = println(t)
Give that a try!

Making Typeclass Instance with `implicit def`?

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

Enforce a lower-bounds that "excludes" a super type

Bounds in Scala allow more granular control of types in Scala, for example argument types.
For example
def foo[ S <: String ]( arg: S ): S = ...
The above allows a function to accept arguments that are sub types of String, also
def bar[ S >: A <: B ]( arg: S ): S = ...
The above allows the setting of an upper and lower bound so that S is a sub type of B and a super type of A.
My question is (I assume the bounds are inclusive) would it be possible to set up an argument type so that the argument would be a supertype of say String, but not include some super type of the lower bound (in this case String) say type Any.
UPDATE
sealed trait Helper[S]
object Helper {
implicit def stringSubtype[S >: String] = new Helper[S]{}
implicit def any = new Helper[Any]{}
}
def foo[S: Helper](r: S): Int = 1
val arg1: String = "hi"
val arg2: Any = "hello"
foo(arg1)
foo(arg2)
I would expect that the call with arg2 should result in an illegal argument exception.
For more complex type constraints like this you can do type-level programming via implicits:
sealed trait Helper[S]
object Helper {
implicit def stringSubtype[S >: String] = new Helper[S]{}
implicit def any = new Helper[Any]{}
implicit def any2 = new Helper[Any]{}
}
def foo[S: Helper] = ...
foo can only be invoked with a type S for which an implicit Helper[S] can be resolved. stringSubtype supplies a Helper[S] for any S >: String. But for Any, both that and any apply and the two implicits conflict, so it's not possible (well, except by explicitly passing one or the other) to call foo[Any].
Update: it seems that any is somehow higher priority than stringSubtype, so it's resolved for foo[Any]. Rather than figure out exactly why this is, the simplest workaround was to also define any2.

Defining a method whose return type is the singleton type of an argument of that method

Still struggling with this.types (singleton types). Assume this scenario:
trait Sys[A <: Access] {
def in[T](v: String): AccessPrepare[A]
}
trait AccessPrepare[A <: Access] {
val a: A
def apply[T](fun: a.type => T): T
}
object Ref {
def single[A <: Access, V](v: V)(implicit a: A): Ref[A, V] = ???
}
trait Ref[A, V]
trait Access {
def set(r: Ref[this.type, Int]): Unit
}
The following fails:
def test(sys: Sys[Access]): Unit =
sys.in("v1") { implicit a =>
val r = Ref.single(44)
a.set(r)
}
because apparently r is of type Ref[Access, Int] and not Ref[a.type, Int]. My guess is the problem is that I would need a line like
def single[A <: Access, V](v: V)(implicit a: A): Ref[a.type, V] = ...
which isn't compiling as due to "illegal dependent method type"...
Any ideas how I can fix this. The demand is that I do not explicitly annotate calls with types. That is, I do not want to write Ref.single[a.type, Int](44)(a) for comprehensible reasons.
EDIT
As a clarification, with reference to answer "FYI, and to close the question" in thread Constraining an operation by matching a type parameter to an argument's path-dependent type -- what I would like to have in addition is the possibility to create objects (Refs) not by using a factory method in the Access but somewhere outside (e.g. with a new statement). Because the system cannot be limited by the definition of Access, I must be able to extend it with further objects.
You have several possibilities. With Scala 2.8/2.8.1, you can use the private option -Ydependent-method-types and then your solution with
def single[ A <: Access, V ]( v: V )( implicit a: A ) : Ref[ a.type, V ] = // ...
compiles fine.
If you want to avoid dependent method types because it's a private option, you can still make your first proposal compile by explicitly typing the call to Ref.single:
val r = Ref.single[a.type, Int](44)
You need to specify the type, though, as singleton types are never inferred. You problem is not the same as, but related to, the problem that singleton types are not inferred: see How to correctly type-annotate this HList?