I have a function like this:
case class SomeCaseClass(i: Int)
def func[T: Manifest](someArg: Int)(implicit i: String) = {
SomeCaseClass(2)
}
I need to call func and supply i explicitly
but when I call func[SomeCaseClass](2)("hello"), I get:
error: not enough arguments for method func: (implicit evidence$1:
Manifest[ScalaFiddle.this.SomeCaseClass], implicit i:
String)ScalaFiddle.this.SomeCaseClass. Unspecified value parameter i.
funcSomeCaseClass("hello")
Any way to do it without changing the function's signature?
You need to give all implicit parameters explicitly if you give any, and T: Manifest means there is an additional implicit parameter.
Happily, implicitly method will summon the implicit which the compiler would have supplied:
func[SomeCaseClass](2)(implicitly, "hello") // inferred to implicitly[Manifest[SomeCaseClass]]
When I define the method func in my scala REPL, I am finding the output as:
func: [T](someArg: Int)(implicit evidence$1: Manifest[T], implicit i: String)SomeCaseClass
In other words, the same code can also be written as:
def func1[T](someArg: Int)(implicit manifest: Manifest[T], i: String) = {
SomeCaseClass(2)
}
It is described here as well.
So in the above code, we can see that the implicit section now have two parameters, not the only String. And you need to provide all the params of the implicit section in case you want to fill them explicitly. If you're providing just one it will throw a compilation error.
Hence your method func can be called through the below code:
func(2)(Manifest.classType(classOf[SomeCaseClass]), "hello")
Related
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.
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!
I have the following simple test-case:
trait Printable[T] {
val string: String
def print() = println("It works: " + string)
}
def foo[T](x: T)(implicit ev: T => Printable[T]) = {
x.print()
}
implicit def doubleToPrint(x: Double): Printable[Double] = new Printable[Double] {
override val string: String = x.toString
}
foo(2.0) // => It works: 2.0
However, creating a new function bar[T](x: T) which should call foo(x) raises an error that there is no implicit view available from T => Printable[T] :
// this does not work
def bar[T](x: T) = {
println("Some other stuff")
foo(x)
}
However, when adding the same parameter it works ofcourse:
// this does work
def bar[T](x: T)(implicit ev: T => Printable[T]) = {
println("Some other stuff")
foo(x)
}
It seems to me quite cumbersome to keep chaining these implicit parameters, because I was under the assumption that the foo function will start searching for the implicit conversion and not the function bar calling foo. As I understand the implicit def doubleToPrint should be in scope for foo also when it is being called from within foo.
What am I overlooking?
Additional question in response to the answer of dth
So I understand the answer, which is actually very logical.
However, the solution of the context bounds does not work in the situation where foo and bar are both part of another trait, since context bounds are not allowed in traits:
// not allowed to do trait FooBar[T : Printable]
trait FooBar[T] {
def foo(x: T)(implicit ev: T => Printable[T]) = {
println("Running foo...")
x.print()
}
// this is not allowed
def bar(x: T) = {
println("But running bar first...")
foo(x)
}
}
So is it also possible to solve this without using the implicit parameter?
My own, not so nice, solution
I came to the conclusion that I actually don't need a trait in my specific code and can replace the FooBar[T] trait with an abstract class FooBar[T <% Printable[T]].
It is a solution for my problem, but not the additional question I added.
Think about, how implicit parameters work:
When you call a method requiring an implicit parameter somewhere the compiler looks in the context (scope, involved types) for a suitable implicit.
Now look at your definition of bar:
def bar[T](x: T) = {
foo(x)
}
When you call foo the compiler looks for an implicit value of the type T => Printable[T] which it cannot find. It does not matter, that you will call bar later with a type Double as it does not know that.
So the answer is yes, you have to pass implicit parameters around everywhere, where you can not find a suitable value in the context (so usually everywhere, where you do not know the concrete type).
There is however syntactic sugar called context bounds, so you can define bar like this:
def bar[T: Printable](x: T) = foo(x)
You could also define foo like this and use implicitly[Printable[T]] to access the values. So you do not have to concern yourself with implicit parameters at all in simple setting like this.
Traits
Context bounds are just syntactic sugar for an implicit parameter. The implicit value is passed where you define the type bound. I.e. if it is the type parameter of a method it is passed to the method.
A trait may not have any constructor parameters as due to linearisation you do not no where it will end up in the inheritance hierarchy. Thus it may not have any implicit parameters or type bounds either.
So you really have to add an implicit parameter to both methods.
If you are implementing some complex API this is fine, if this appears a lot in user code, maybe you can change your design.
Classes
You can use context bounds for type parameters of classes, however the implicit parameter will not be directly used inside of methods of that class. To achieve that you have to provide a local implicit conversion like this:
class FooBar[T: Printable] {
implicit def conv(x: T) = implicitly[Printable[T]]
def foo(x: T) = {
println("Running foo...")
x.print()
}
def bar(x: T) = {
println("But running bar first...")
foo(x)
}
}
View Bounds
There are also view bounds as an alternative. They have however been deprecated. If you run scalac with -Xfuture it will show you that.
The problem here is the type T.
Means, that without
(implicit ev: T => Printable[T])
the compiler tries to find an implicit that would work for any type of T
which he can not, because there is an implicit only for Double.
But if you add
(implicit ev: T => Printable[T])
the compiler tries to find the implicit at the place you call bar.
And if you call it with a Double parameter he takes doubleToPrint and passes it by.
I have a map of String to Functions which details all of the valid functions that are in a language. When I add a function to my map, I am required to specify the type (in this case Int).
var functionMap: Map[String, (Nothing) => Any] = Map[String, (Nothing) => Any]()
functionMap += ("Neg" -> expr_neg[Int])
def expr_neg[T: Numeric](value: T)(implicit n: Numeric[T]): T = {
n.negate(value)
}
Instead, how can I do something like:
functionMap += ("Neg" -> expr_neg)
without the [Int] and add it in later on when I call:
(unaryFunctionMap.get("abs").get)[Int](-45)
You're trying to build your function using type classes (in this case, Numeric). Type classes rely on implicit parameters. Implicits are resolved at compile time. Your function name string values are only known at runtime, therefore you shouldn't build your solution on top of type classes like this.
An alternative would be to store a separate function object in your map for each parameter type. You could store the parameter type with a TypeTag:
import scala.reflect.runtime.universe._
var functionMap: Map[(String, TypeTag[_]), (Nothing) => Any] = Map()
def addFn[T: TypeTag](name: String, f: T => Any) =
functionMap += ((name, typeTag[T]) -> f)
def callFn[T: TypeTag](name: String, value: T): Any =
functionMap((name, typeTag[T])).asInstanceOf[T => Any](value)
addFn[Int]("Neg", expr_neg)
addFn[Long]("Neg", expr_neg)
addFn[Double]("Neg", expr_neg)
val neg10 = callFn("Neg", 10)
No type class implicit needs to be resolved to call callFn(), because the implicit Numeric was already resolved on the call to addFn.
What happens if we try to resolve the type class when the function is called?
The first problem is that a Function1 (or Function2) can't have implicit parameters. Only a method can. (See this other question for more explanation.) So if you want something that acts like a Function1 but takes an implicit parameter, you'll need to create your own type that defines the apply() method. It has to be a different type from Function1, though.
Now we get to the main problem: all implicits must be able to be resolved at compile time. At the location in code where the method is run, all the type information needed to choose the implicit value needs to be available. In the following code example:
unaryFunctionMap("abs")(-45)
We don't really need to specify that our value type is Int, because it can be inferred from the value -45 itself. But the fact that our method uses a Numeric implicit value can't be inferred from anything in that line of code. We need to specify the use of Numeric somewhere at compile time.
If you can have a separate map for unary functions that take a numeric value, this is (relatively) easy:
trait UnaryNumericFn {
def apply[T](value: T)(implicit n: Numeric[T]): Any
}
var unaryNumericFnMap: Map[String, UnaryNumericFn] = Map()
object expr_neg extends UnaryNumericFn {
override def apply[T](value: T)(implicit n: Numeric[T]): T = n.negate(value)
}
unaryNumericFnMap += ("Neg" -> expr_neg)
val neg3 = unaryNumericFnMap("Neg")(3)
You can make the function trait generic on the type class it requires, letting your map hold unary functions that use different type classes. This requires a cast internally, and moves the specification of Numeric to where the function is finally called:
trait UnaryFn[-E[X]] {
def apply[T](value: T)(implicit ev: E[T]): Any
}
object expr_neg extends UnaryFn[Numeric] {
override def apply[T](value: T)(implicit n: Numeric[T]): T = n.negate(value)
}
var privateMap: Map[String, UnaryFn[Nothing]] = Map()
def putUnary[E[X]](key: String, value: UnaryFn[E]): Unit =
privateMap += (key -> value)
def getUnary[E[X]](key: String): UnaryFn[E] =
privateMap(key).asInstanceOf[UnaryFn[E]]
putUnary("Neg", expr_neg)
val pos5 = getUnary[Numeric]("Neg")(-5)
But you still have to specify Numeric somewhere.
Also, neither of these solutions, as written, support functions that don't need type classes. Being forced to be this explicit about which functions take implicit parameters, and what kinds of implicits they use, starts to defeat the purpose of using implicits in the first place.
You can't. Because expr_neg is a method with a type parameter T and an implicit argument n depending on that parameter. For Scala to lift that method to a function, it needs to capture the implicit, and therefore it must know what kind of type you want.
How would one encode the following constraint in Scala (pseudocode)?
def foo(x: T forSome { type T has a Numeric[T] instance in scope }) = {
val n= implicitly[...] // obtain the Numeric instance for x
n.negate(x) // and use it with x
}
In words: I need a type class instance for my input argument, but I don't care about the argument's type, I just need to obtain the instance and use it on my argument.
It doesn't have to be an existential type, but I need to avoid type parameters in the def's signature.
Edit: just to clarify, the standard approach in these cases, i.e.:
def foo[T: Numeric](x: T) = ...
doesn't work for me, as it requires the addition of a type parameter on the method.
Thanks.
I managed to make it work like this:
implicit class InstanceWithNumeric[T](val inst: T)(implicit val n: Numeric[T])
def foo(iwn: InstanceWithNumeric[_]) {
def genFoo[T](iwn: InstanceWithNumeric[T]) {
println(iwn.n.negate(iwn.inst))
}
genFoo(iwn)
}
And now:
scala> foo(1)
-1
scala> foo(1.2)
-1.2
Not the prettiest, but seems to work.
EDIT: You can avoid defining inner function like this:
implicit class InstanceWithNumeric[T](val inst: T)(implicit val n: Numeric[T]) {
def negate = n.negate(inst)
}
Also, if you want to make implicit conversion to InstanceWithNumeric globally visible, you can do something like this:
class InstanceWithNumeric[T](val inst: T)(implicit val n: Numeric[T])
object InstanceWithNumeric {
implicit def apply[T: Numeric](inst: T) =
new InstanceWithNumeric(inst)
}
If you want to understand how this works, read about so called implicit scope (this question seems to contain good explanation).
Not quite sure what you are attempting, because it seems you need a type once you make the call to implicitly. Would the following work for you?
def foo(implicit x: Numeric[_]) {
//code goes here.
}