Scala implicit parameters need to be repeated? - scala

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.

Related

How to reference parameter of a higher kinded type parameteter?

Suppose you have a trait like this:
trait Foo[A]{
def foo: A
}
I want to create a function like this:
def getFoo[A <: Foo[_]](a: A) = a.foo
The Scala Compiler deduces Any for the return type of this function.
How can I reference the anonymous parameter _ in the signature (or body) of getFoo?
In other words, how can I un-anonymize the parameter?
I want to be able to use the function like
object ConcreteFoo extends Foo[String] {
override def foo: String = "hello"
}
val x : String = getFoo(ConcreteFoo)
which fails compilation for obvious reasons, because getFoo is implicitly declared as Any.
If this is not possible with Scala (2.12 for that matter), I'd be interested in the rational or the technical reason for this limitation.
I am sure there are articles and existing questions about this, but I appear to be lacking the correct search terms.
Update: The existing answer accurately answers my question as stated, but I suppose I wasn't accurate enough regarding my actual usecase. Sorry for the confusion. I want to be able to write
def getFoo[A <: Foo[_]] = (a: A) => a.foo
val f = getFoo[ConcreteFoo.type]
//In some other, unrelated place
val x = f(ConcreteFoo)
Because I don't have a parameter of type A, the compiler can't deduce the parameters R and A if I do
def getFoo[R, A <: Foo[R]]: (A => R) = (a: A) => a.foo
like suggested. I would like to avoid manually having to supply the type parameter R (String in this case), because it feels redundant.
To answer literally your exact question:
def getFoo[R, A <: Foo[R]](a: A): R = a.foo
But since you don't make any use of the type A, you can actually omit it and the <: Foo[..] bound completely, retaining only the return type:
def getFoo[R](a: Foo[R]): R = a.foo
Update (the question has been changed quite significantly)
You could smuggle in an additional apply invocation that infers the return type from a separate implicit return type witness:
trait Foo[A] { def foo: A }
/** This is the thing that remembers the actual return type of `foo`
* for a given `A <: Foo[R]`.
*/
trait RetWitness[A, R] extends (A => R)
/** This is just syntactic sugar to hide an additional `apply[R]()`
* invocation that infers the actual return type `R`, so you don't
* have to type it in manually.
*/
class RetWitnessConstructor[A] {
def apply[R]()(implicit w: RetWitness[A, R]): A => R = w
}
def getFoo[A <: Foo[_]] = new RetWitnessConstructor[A]
Now it looks almost like what you wanted, but you have to provide the implicit, and you have to call getFoo[ConcreteFoo.type]() with additional pair of round parens:
object ConcreteFoo extends Foo[String] {
override def foo: String = "hey"
}
implicit val cfrw = new RetWitness[ConcreteFoo.type, String] {
def apply(c: ConcreteFoo.type): String = c.foo
}
val f = getFoo[ConcreteFoo.type]()
val x: String = f(ConcreteFoo)
I'm not sure whether it's really worth it, it's not necessarily the most straightforward thing to do. Type-level computations with implicits, hidden behind somewhat subtle syntactic sugar: that might be too much magic hidden behind those two parens (). Unless you expect that the return type of foo will change very often, it might be easier to just add a second generic argument to getFoo, and write out the return type explicitly.

Scala: Implicit evidence for generic types

Assume there are such two traits:
trait Fooer[-T] {
def foo(x: T): Unit
}
trait CanFoo[-T] {
def fooer: Fooer[T]
}
And a function:
def bar[T: CanFoo](x: T) = {
implicitly[CanFoo[T]].fooer.foo(x)
}
Everything works so far. However, I was stuck when trying to make bar work recursively on collection types like Seq[T] (i.e. bar[Seq[T]](seq) recursively calls bar[T] on seq's elements). I can't do implicit object CanFooSeq extends CanFoo[Seq[_]] since that would cause the type information of the elements to be lost. (I also tried to make another function def bar[T: CanFoo](seq: Seq[T]) = ..., but that didn't solve the problem either since Seq[T] still isn't being recognized as a Foo-able type.)
Is there any way to solve this problem?
implicit def CanFooSeq[T]: CanFoo[Seq[T]] = new CanFoo[Seq[T]] { def fooer = ... }
(if you want to have it only in case you have CanFoo[T], add the implicit parameter: implicit def CanFooSeq[T: CanFoo]: CanFoo[Seq[T]] = new CanFoo[Seq[T]] { def fooer = ... }) if I understood the question correctly. Note it has to be a def, because objects and vals can't have type parameters, so a new one will be created on each call (which is very unlikely to matter for performance in practice).

How can I write a function have a polymorphic return type based on the type argument of its type parameter?

I have some code like this:
sealed trait Foo[A] {
def value: A
}
case class StringFoo(value: String) extends Foo[String]
case class IntFoo(value: Int) extends Foo[Int]
I'd like to have a function which can use the A type given a subtype's type parameter.
// Hypothetical invocation
val i: Int = dostuff[IntFoo](param)
val s: String = dostuff[StringFoo](param)
I can't figure out how to declare dostuff in a way that works. The closest thing I can figure out is
def dostuff[B <: Foo[A]](p: Param): A
But that doesn't work because A is undefined in that position. I can do something like
def dostuff[A, B <: Foo[A]](p: Param): A
But then I have to invoke it like dostuff[String, StringFoo](param) which is pretty ugly.
It seems like the compiler should have all the information it needs to move A across to the return type, how can I make this work, either in standard scala or with a library. I'm on scala 2.10 currently if that impacts the answer. I'm open to a 2.11-only solution if it's possible there but impossible in 2.10
Another option is to use type members:
sealed trait Foo {
type Value
def value: Value
}
case class StringFoo(value: String) extends Foo { type Value = String }
case class IntFoo(value: Int) extends Foo { type Value = Int }
def dostuff[B <: Foo](p: Any): B#Value = ???
// Hypothetical invocation
val i: Int = dostuff[IntFoo](param)
val s: String = dostuff[StringFoo](param)
Note that both solutions mainly work around the syntactic restriction in Scala, that you cannot fix one type parameter of a list and have the compiler infer the other.
As you might know, if you have a parameter of type Foo[A], then you can make the method generic in just A:
def dostuff[A](p: Foo[A]): A = ???
Since that might not always be the case, we can try to use an implicit parameter that can express the relationship between A and B. Since we can't only apply some of the generic parameters to a method call (generic parameter inference is all or nothing), we have to split this into 2 calls. This is an option:
case class Stuff[B <: Foo[_]]() {
def get[A](p: Param)(implicit ev: B => Foo[A]): A = ???
}
You can check the types in the REPL:
:t Stuff[IntFoo].get(new Param) //Int
:t Stuff[StringFoo].get(new Param) //String
Another option along the same lines, but using an anonymous class, is:
def stuff[B <: Foo[_]] = new {
def apply[A](p: Param)(implicit ev: B <:< Foo[A]): A = ???
}
:t stuff[IntFoo](new Param) //Int
Here, I've used apply in stead of get, so you can apply the method more naturally. Also, as suggested in your comment, here I've used <:< in the evidence type. For those looking to learn more about this type of generalized type constraint, you can read more here.
You might also consider using abstract type members instead of generic parameters here. When struggling with generic type inference, this often provides an elegant solution. You can read more about abstract type members and their relationship to generics here.

Generic bounds, most of them are unclear

It's kind of complicated to learn Scala's generic bounds. I know that:
T : Tr - T has type of Tr, meaning it implements a trait Tr
T <: SuperClass - T is subclass of SuperClass
T :> ChildClass - T is superclass of ChildClass
However, there are also many more operators:
<% and %>
=:=
<:< and >:>
<% and %>
<%< and >%>
I read about them, but as I said, there was was not comprehensible explanations. Could you make it clearer?
I've used a few type constraints:
The easiest are <: and >:. These are simple bounds on the type hierarchy.
trait A
trait B extends A
trait C extends B
then for a method
def doSomething[T >:C <:B](data:T)
either B or C can be substituted instead of T
Then type constraints that involves an addition of implicit parameter to the method.
def doSmth1[T: MyTypeInfo] (data:T)
is rewritten during compilation as
def doSmth1[T] (data:T)(implicit ev: MyTypeInfo[T])
whereas
def doSmth2[T <% SomeArbitratyType] (data:T)
is rewritten as
def doSmth2[T] (data:T)(implicit ev: T => SomeArbitratyType)
Both of the methods can be called if in the scope there is an instance that fits the implicit parameter. If there is no appropriate instance then compiler issues an error.
The view bound (<%) requires an implicit conversion that converts T to an instance of the other type (SomeArbitratyType).
More powerful is using "type classes". Inside the type class instance one may put many useful methods that can deal with the type T. In particular, one may put a conversion method and achieve similar result as view bounds.
Examples:
trait MyTypeInfo[T] {
def convertToString(data:T):String
}
def printlnAdv[T : MyTypeInfo](data:T) {
val ev = implicitly[MyTypeInfo[T]]
println(ev.convertToString(data))
}
somewhere in the scope there should be implicit value of type MyTypeInfo[T]:
implicit val doubleInfo = new MyTypeInfo[Double] {
def convertToString(data:Double):String = data.toString
}
or
implicit def convertToString(data:T):String
def printlnAdv[T <% String](data:T) {
val conversionResult = data : String
println(conversionResult)
}
somewhere in the scope there should be implicit function:
implicit def convertDoubleToString(data:Double):String = data.toString
The next weird symbols are =:= and <:<. These are used in methods that wish to ensure that a type has some property. Of course, if you declare a generic parameter then it is enough to have <: and >: to specify the type. However, what to do with types that are not generic parameters? For instance, the generic parameter of an enclosing class, or some type that is defined within another type. The symbols help here.
trait MyAlmostUniversalTrait[T] {
def mySpecialMethodJustForInts(data:T)(implicit ev:T =:= Int)
}
The trait can be used for any type T. But the method can be called only if the trait is instantiated for Int.
Similar use case exists for <:<. But here we have not "equals" constraint, but "less than" (like T<: T2).
trait MyAlmostUniversalTrait[T] {
def mySpecialMethod(data:T)(implicit ev:T <:< MyParentWithInterestingMethods)
}
Again the method can only can called for types that are descendants of MyParentWithInterestingMethods.
Then <%< is very similar to <%, however it is used the same way as <:< — as an implicit parameter when the type is not a generic parameter. It gives a conversion to T2:
trait MyAlmostUniversalTrait[T] {
def mySpecialMethod(data:T)(implicit ev:T <%< String) {
val s = data:String
...
}
}
IMHO <%< can safely be ignored. And one may simply declare the required conversion function:
trait MyAlmostUniversalTrait[T] {
def mySpecialMethod(data:T)(implicit ev:T => String) {
val s = data:String
...
}
}

Typeclass instances for unnamed types in Scala

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