Implicit String conversion in scala doesnt compile - scala

I've attempted to implement an implicit string conversion, as an experiment with creating scala object "factories", for example, in this case, I'd like to create an employee object from a string.
implicit def s2act(name: String) = new Actor[Employee](){
override def toString() : String = {
name
}
};
//two failed attempts at leveraging the implicit conversion below...
processActor("jim")
def boss : Actor = new String("Jim");
However, the above implicit binding fails to be identified by the compiler. Why does the compiler fail to process this implicit binding?

It seems to me that the error you should get from your code is that "class Actor takes type parameters".
a more correct code will be :
def boss : Actor[Employee] = new String("Jim");

I don't know what's the signature of processActor, but judging from the signature of boss I think the problem is you don't provide type parameter to Actor.
Actor itself is a type constructor, which means that it takes a type to construct a new type.
Actor is not a type, and you cannot use it in your function/method signature, but Actor[Employee] is a type.
Change your boss to this
def boss: Actor[Employee] = new String("Jim")
Related post: What is a higher kinded type in Scala?

Related

Scala Implicit Parameters Projection Conflict , "Ambigious Implicit Values" Error

I have been reading Bruno's TypeClasses paper and he mentioned that implicits in the argument list are projected/propagated into the implicit scope. I followed the example with this code:
package theory
import cats.implicits.toShow
import java.io.PrintStream
import java.util.Date
object Equality extends App {
import cats.Eq
// assert(123 == "123")
println(Eq.eqv(123, 123).show)
implicit val out: PrintStream = System.out
def log(m: String)(implicit o: PrintStream ): Unit =
o.println(m)
def logTime(m: String)(implicit o: PrintStream): Unit =
log(s"${new Date().getTime} : $m")
}
The kicker is that this code will not compile, with:
ambiguous implicit values:
both value out in object Equality of type java.io.PrintStream
and value o of type java.io.PrintStream
match expected type java.io.PrintStream
log(s"${new Date().getTime} : $m")
So, I assume that the compiler sees 2 instances of the same implicit and complains. I was able to silence the compiler by explicitly adding the PrintStream passed as an argument as the second argument to log:
def logTime(m: String)(implicit o: PrintStream): Unit =
log(s"${new Date().getTime} : $m")(o)
This works, but am I missing something? Why is there confusion inside the body of logTime()? I thought Bruno was implying that the implicit from the caller would be projected into the scope of the method. His example does not add the extra parameter to the log() call. Why does scalac see these as 2? I suppose I assumed that the implicit from the outer method would "hide" the val out. Not so.
If anyone can explain why I see this, it would be appreciated.
Recall that the value of an implicit parameter is determined at the call site. That's why...
Equality.log("log this")
...won't compile unless an implicit value of the appropriate type is brought into scope.
implicit val ps: PrintStream = ...
Equality.log("log this")
The logTime() definition code is a call site for the log() method and, since it is defined within the Equality object, it has the implicit val out value available to it. But it is also the recipient of the implicit o value of the same type that was passed from its call site. Thus the ambiguity. Should the compiler send the implicit out value or the implicit o value to the log() method?
Now, it might seem a bit odd that the received implicit value (from the call site) is both assigned to a local identifier, o, and inserted into the local implicit namespace as well. It turns out that Scala-3 has modified that behavior and your code compiles without error, even without the new given/using syntax. (I assume the implicit out value is passed to the log() method and not the received o value.)

Getting name of parameterized class in scala using shapeless

I want to get the name of a class passed as a parameter to a function using shapeless. I've tried this:
def sayMyName[T](t: T): String = Typeable[T].describe // error: class type required but T found
If T is replaced with a concrete type, there's no problem. Is it possible to make something like this work using shapeless?
You just need to add Typeable typeclass as context bound of your type T:
def sayMyName[T: Typeable](t: T): String = Typeable[T].describe
sayMyName("") //String
You could also explicitly declare implicit parameter:
def sayMyName[T](t: T)(implicit typeable: Typeable[T]): String = Typeable[T].describe
By adding context bound you're asking the compiler to wait with resolving Typeable
typeclass until sayMyName is called with the concrete type, not resolve it right away (which is impossible, since the real type of T is not yet known at this point).

Scala: Type parameters and inheritance

I'm seeing something I do not understand. I have a hierarchy of (say) Vehicles, a corresponding hierarchy of VehicalReaders, and a VehicleReader object with apply methods:
abstract class VehicleReader[T <: Vehicle] {
...
object VehicleReader {
def apply[T <: Vehicle](vehicleId: Int): VehicleReader[T] = apply(vehicleType(vehicleId))
def apply[T <: Vehicle](vehicleType VehicleType): VehicleReader[T] = vehicleType match {
case VehicleType.Car => new CarReader().asInstanceOf[VehicleReader[T]]
...
Note that when you have more than one apply method, you must specify the return type. I have no issues when there is no need to specify the return type.
The cast (.asInstanceOf[VehicleReader[T]]) is the reason for the question - without it the result is compile errors like:
type mismatch;
found : CarReader
required: VehicleReader[T]
case VehicleType.Car => new CarReader()
^
Related questions:
Why cannot the compiler see a CarReader as a VehicleReader[T]?
What is the proper type parameter and return type to use in this situation?
I suspect the root cause here is that VehicleReader is invariant on its type parameter, but making it covariant does not change the result.
I feel like this should be rather simple (i.e., this is easy to accomplish in Java with wildcards).
The problem has a very simple cause and really doesn't have anything to do with variance. Consider even more simple example:
object Example {
def gimmeAListOf[T]: List[T] = List[Int](10)
}
This snippet captures the main idea of your code. But it is incorrect:
val list = Example.gimmeAListOf[String]
What will be the type of list? We asked gimmeAListOf method specifically for List[String], however, it always returns List[Int](10). Clearly, this is an error.
So, to put it in words, when the method has a signature like method[T]: Example[T] it really declares: "for any type T you give me I will return an instance of Example[T]". Such types are sometimes called 'universally quantified', or simply 'universal'.
However, this is not your case: your function returns specific instances of VehicleReader[T] depending on the value of its parameter, e.g. CarReader (which, I presume, extends VehicleReader[Car]). Suppose I wrote something like:
class House extends Vehicle
val reader = VehicleReader[House](VehicleType.Car)
val house: House = reader.read() // Assuming there is a method VehicleReader[T].read(): T
The compiler will happily compile this, but I will get ClassCastException when this code is executed.
There are two possible fixes for this situation available. First, you can use existential (or existentially quantified) type, which can be though as a more powerful version of Java wildcards:
def apply(vehicleType: VehicleType): VehicleReader[_] = ...
Signature for this function basically reads "you give me a VehicleType and I return to you an instance of VehicleReader for some type". You will have an object of type VehicleReader[_]; you cannot say anything about type of its parameter except that this type exists, that's why such types are called existential.
def apply(vehicleType: VehicleType): VehicleReader[T] forSome {type T} = ...
This is an equivalent definition and it is probably more clear from it why these types have such properties - T type is hidden inside parameter, so you don't know anything about it but that it does exist.
But due to this property of existentials you cannot really obtain any information about real type parameters. You cannot get, say, VehicleReader[Car] out of VehicleReader[_] except via direct cast with asInstanceOf, which is dangerous, unless you store a TypeTag/ClassTag for type parameter in VehicleReader and check it before the cast. This is sometimes (in fact, most of time) unwieldy.
That's where the second option comes to the rescue. There is a clear correspondence between VehicleType and VehicleReader[T] in your code, i.e. when you have specific instance of VehicleType you definitely know concrete T in VehicleReader[T] signature:
VehicleType.Car -> CarReader (<: VehicleReader[Car])
VehicleType.Truck -> TruckReader (<: VehicleReader[Truck])
and so on.
Because of this it makes sense to add type parameter to VehicleType. In this case your method will look like
def apply[T <: Vehicle](vehicleType: VehicleType[T]): VehicleReader[T] = ...
Now input type and output type are directly connected, and the user of this method will be forced to provide a correct instance of VehicleType[T] for that T he wants. This rules out the runtime error I have mentioned earlier.
You will still need asInstanceOf cast though. To avoid casting completely you will have to move VehicleReader instantiation code (e.g. yours new CarReader()) to VehicleType, because the only place where you know real value of VehicleType[T] type parameter is where instances of this type are constructed:
sealed trait VehicleType[T <: Vehicle] {
def newReader: VehicleReader[T]
}
object VehicleType {
case object Car extends VehicleType[Car] {
def newReader = new CarReader
}
// ... and so on
}
Then VehicleReader factory method will then look very clean and be completely typesafe:
object VehicleReader {
def apply[T <: Vehicle](vehicleType: VehicleType[T]) = vehicleType.newReader
}

Can I use nested type in Scala generic function?

How can I use nested type in Scala generic function ? I'd like to implement something like this
implicit def basicDBList2List[List[A]](value : BasicDBList) = value.toList.asInstanceOf[List[A]]
Compiler gives following error:
scala: not found: type A
implicit def basicDBList2List[List[A]](value : BasicDBList) = value.toList.asInstanceOf[List[A]]
^
When you write:
implicit def basicDBList2List[List[A]](value: BasicDBList) = ...
... that doesn't mean what you think it means. You're declaring a new type parameter called List, not referring to the existing List trait in the library! You're also declaring that your newly-defined List type requires some type parameter, which you've called A, but you can't actually reference it.
What you probably meant was:
implicit def basicDBList2List[A](value: BasicDBList): List[A] = ...
... which says that, for any type A, you can convert a BasicDBList to a List[A].
This is sketchy code, though, for two reasons:
What type does your BasicDBList class actually contain? Probably not any possible A. You'll very likely get ClassCastException at runtime.
Why do you want an implicit conversion from BasicDBList to List[A]? That's almost always a bad idea.
I think it is better have it like:
implicit def basicDBList2List[A](value : BasicDBList) = value.toList.asInstanceOf[List[A]]

Could not find implicit value for evidence parameter of type scala.reflect.ClassManifest[T]

It seems I don't understand something important, maybe about erasure (damn it).
I have a method, which I wanted to create array of size n filled with values from gen:
def testArray[T](n: Int, gen: =>T) {
val arr = Array.fill(n)(gen)
...
}
And use it, for example as:
testArray(10, util.Random.nextInt(10))
But I get error:
scala: could not find implicit value for evidence parameter of type scala.reflect.ClassManifest[T]
val arr = Array.fill(n)(gen)
^
Please, explain what I did wrong, why this error, and what kind of code it makes impossible?
That is because in testArray the concrete type of T is not known at compile time. Your signature has to look like def testArray[T : ClassManifest](n: Int, gen: =>T), this will add an implicit parameter of type ClassManifest[T] to your method, that is automatically passed to the call of testArray and then further passed to the Array.fill call. This is called a context bound.
The Array.fill method has the following signature:
def fill[T](n: Int)(elem: => T)(implicit arg0: ClassManifest[T]): Array[T]
In order to get an instance of ClassManifest[T] you need to know the concrete type. A ClassManifest can be obtained like this:
implicitly[ClassManifest[String]]
A ClassManifest is implicitly available for every concrete type.
For any implicit error, you can add the implicits you require to the method with the type parameter:
def wrap[T](n:Int)(elem: => T)(implicit c:ClassManifest[T], o:Ordering[T])
If you did not yourself introduce ClassManifest or Ordering, the writers of the library have (most likely) provided sensible defaults for you.
If you would call the wrap method:
wrap(2)(3)
It's expanded like this:
wrap[Int](2)(3)(implicitly[ClassManifest[Int]], implicitly[Ordering[Int]])
If you introduced a custom class Person here, you would get an error for not finding an implicit instance of Ordering[Person]. The writers of the library could not have known how to order Person. You could solve that like this:
class Person
implicit val o = new Ordering[Person] { // implement required methods }
wrap(2)(new Person)
The Scala compiler looks in different scopes for implicits, an Ordering would usually not be specified like this. I suggest you look up implicit resolution on the internet to learn more about it.