What's the point of implicit conversions as parameters? - scala

I'm reading the docs on implicits in Scala, and there is an example of a function with implicit conversion as parameter:
def getIndex[T, CC](seq: CC, value: T)(implicit conv: CC => Seq[T]) = seq.indexOf(value)
I understand how it works, but I don't understand what's the point of writing it like that instead of:
def getIndexExplicit[T](seq: Seq[T], value: T) = seq.indexOf(value)
As far as I know, if the conversion from the argument seq to type Seq[T] exists, the compiler would still allow the call to getIndexExplicit?
To illustrate my point, I prepared this simple example:
def equal42[T](a: T)(implicit conv: T => Int) = conv(a) == 42 // implicit parameter version
def equal42Explicit(a: Int) = a == 42 // just use the type in the signature
implicit def strToInt(str: String): Int = java.lang.Integer.parseInt(str) // define the implicit conversion from String to Int
And indeed, both functions seem to work in the same way:
scala> equal42("42")
res12: Boolean = true
scala> equal42Explicit("42")
res13: Boolean = true
If there is no difference, what's the point of explicitly defining the implicit conversion?
My guess is that in this simple case it makes no difference, but there must be some more complex scenarios where it does. What are those?

In your super-simple example:
equal42("42")
equal42Explicit("42")
is equal to
equal42("42")(strToInt)
equal42Explicit(strToInt("42"))
which in case of your definition make no difference.
BUT if it did something else e.g.
def parseCombined[S, T](s1: S, s2: S)
(combine: (S, S) => S)
(implicit parse: S => Option[T]): Option[T] =
parse(combine(s1, s2))
then when you would apply conversion matters:
implicit def lift[T]: T => Option[T] = t => Option(t)
implicit val parseInt: String => Option[Int] = s => scala.util.Try(s.toInt).toOption
implicit def parseToString[T]: T => Option[String] = t => Option(t.toString)
parseCombined[Option[Int], String]("1", "2") { (a, b) => a.zip(b).map { case (x, y) => x + y } } // Some("Some(3)")
parseCombined[String, Int]("1", "2") { _ + _ } // Some(12)
In the first case arguments were converted before passing (and then again inside), while in the other case they were converted only inside a function at a specific place.
While this case is somewhat stretched, it shows that having control over when conversion is made might matter to the final result.
That being said such usage of implicit conversions is an antipattern and type classes would work much better for it. Actually extension methods are the only non-controversial usages of implicit conversions because even magnet pattern - the only other use case that might be used on production (see Akka) - might be seen as issue.
So treat this example from docs as a demonstration of a mechanism and not as a example of good practice that should be used on production.

Related

Keeping the data type intact when using match-case

This returns Any:
def convertType(data: String, dataType: String) = {
dataType match {
case "Int" => data.toInt
case "Double" => data.toDouble
case "Long" => data.toLong
case "Option[Int]" => Some(data.toInt)
case "Option[Long]" => Some(data.toLong)
case "Option[Double]" => Some(data.toDouble)
}
}
// Isn't this a bad way to solve the problem ?
implicit def anyToInt(str: Any) = str.asInstanceOf[Int]
implicit def anyToLong(str: Any) = str.asInstanceOf[Long]
val i: Int = convertType("1", "Int")
val l: Long = convertType("1", "Long")
What is the best way to keep the original data type intact?
import scala.reflect.runtime.universe._
implicit class StringConverter(data: String) {
private[this] def convert(tag: Type): Any = tag match {
case t if t =:= typeOf[Int] => data.toInt
case t if t =:= typeOf[Double] => data.toDouble
case t if t =:= typeOf[Long] => data.toLong
case t if t =:= typeOf[Option[Int]] => Some(data.toInt)
}
def convert[T](implicit typeTag: TypeTag[T]): T = convert(typeTag.tpe).asInstanceOf[T]
}
scala> "123".convert[Int]
res5: Int = 123
scala> "123".convert[Option[Int]]
res6: Option[Int] = Some(123)
scala> "123".convert[Double]
res7: Double = 123.0
As #Luka Jacobowitz said, convert type with generics:
implicit TypeTag with generic to retrieve type info
Type with case match to parse data
asInstanceOf to cast variable to target type(because it already has checked by TypeTag, it's safe to do that)
What you want to do is slightly tricky. Subtyping, as you've seen, isn't going to get you what you want due to having to return the supertype of all your return types.
Type variables though, might save the day!
def convertType[T](x: String): T = x.asInstanceOf[T]
But that's not quite what you want... You need something that has different behavior based on what T is being passed. Something like (not real Scala)
def convertType[T](x: String): T = T match {
case Double => x.toDouble
case Int => x.toInt
// And all your other cases
}
Unfortunately Scala is not a full-fledged dependently-typed language so we don't have functions that can act directly on types, so that match statement doesn't work.
However, if we provided a value-level "witness" for the type T, maybe we could get away with our conversion.
def convertType[T](x: String)(witness: T): T = witness match {
case _: Double => x.toDouble
case _: Int => x.toInt
// Fill in other cases as necessary
}
We can make this slightly more convenient for ourselves by making the witness implicit. Now that only gets us half-way there because we still need to have weird dummy implicit values sitting around that don't do anything except be witnesses to our function (e.g. randomly we'll need something like implicit val z = 2).
Can we get rid of the need to create these dummy values to pass in as witnesses?
Yes and there's two ways. One is to use Scala's TypeTags which are exactly meant to be value level witnesses of types generated automatically by the compiler.
import scala.reflect.runtime.universe._
def convertTypes[T](x: String)(implicit witness: TypeTag[T]): T = witness match {
case a if a =:= typeOf[Int] => x.toInt
case a if a =:= typeOf[Double] => x.toDouble
}
Alternatively you can move the actual conversion out to a separate trait and have witnesses implement the behavior specified by the trait.
trait Convertable[T] {
def convertFromString(x: String): T
}
implicit object ConvertInt extends Convertable[Int] {
override def convertFromString(x: String): Int = x.toInt
}
// Do the same for your other types
def convertType[T](x: String)(implicit witness: Convertable[T]): T = witness.convertFromString(x)
And there we go! A nice type-safe-ish conversion method (at least this last one is). You'd probably want to wrap the entire thing in a scala.util.Try in case you pass a malformed string.
Incidentally we've just recreated typeclasses (or used Scala's built-in TypeTag typeclass).

Scala: bug in implicit parameter

The following is a simplified version of my real problem:
class Z[T]
object E extends Enumeration {
implicit val z = new Z[Value]
val X, Y = Value
}
implicit def f[T : Z] = (getter: T) => 0
implicit def o[T](v: Option[T])(implicit toInt: T => Int) = 0
def e: Option[E.Value] = null
val b: Int = e
This works, with b implicitly converted to o(e)(f(E.z)). But with the small changes following:
implicit def f[T : Z] = (setter: T => Unit) => 0
implicit def o[T](v: Option[T])(implicit toInt: (T => Unit) => Int) = 0
it fails finding the appropriate implicit value E.z although there's no essential difference from the original code, while manual explicit conversion to o(e)(f(E.z)) still works.
I know the implementation of implicit parameter is not complete yet and there are still many unresolved issues. If this is one of them, I'd like to report it to the Scala contributors. So my question is, a) is this really a bug? b) if so, where and how can I file a bug so that it could be fixed in the future?
UPDATE
Travis' answer worked like a charm! By the way, the code above was a workaround to my original problem:
implicit object E extends Enumeration { val X, Y = Value }
implicit object F extends Enumeration { val X, Y = Value }
implicit def f[T <: Enumeration](getter: T#Value)(implicit e: T) = 0
implicit def o[T](v: Option[T])(implicit toInt: T => Int) = 0
val b: Int = Some[E.Value](null)
In this code, the situation was the other way around: it works with the setter version but not with the simpler getter version. The compiler complains that it's confusing whether to use E or F as the implicit parameter though using F doesn't actually compile nor make sense. I managed to get it working by doing a similar thing:
implicit def f[S <% T => T, T <: Enumeration](getter: T#Value)(implicit e: T) = 0
This works, and although I somehow could get it working, I still don't understand the logic behind this magic.
You've run into a yet another variation of this limitation of Scala's type inference system.
The compiler will resolve the T for f if in the first case, where it's looking for an implicit conversion from plain old E.Value to Int, but not in the second, where it wants a conversion from E.Value => Unit (i.e., Function1[E.Value, Unit]) to Int.
Fortunately there's an easy workaround in cases like this—just use a view bound:
implicit def f[F <% T => Unit, T: Z] = (setter: F) => 0
This will desugar to something like the following:
implicit def f[F, T](implicit st: F <:< (T => Unit), ev: Z[T]) = (setter: F) => 0
Now when the compiler wants a conversion from E.Value => Unit to Int it'll be able to resolve F to E.Value => Unit immediately and then T to E.Value.

How to convert a List[A] into a List[B] using an implicit conversion

I have the following use case which occurs often in my code:
A Collection[A]
An implicit conversion A to B
and I want to obtain a collection of B. I can use implicitly like the following:
case class Items(underlying:List[B])
import B._
def apply(a:List[A]):Items = {
val listOfB= a.map {implicitly[A=>B]}
Items(listOfB)
}
What is the most elegant way to do that in Scala, maybe with the help of Scalaz of doing the same?
Edit: the goal of my question is to find an idiomatic way, a common approach among libraries/developers. In such a sense developing my own pimp-my-library solution is something I dislike, because other people writing my code would not know the existence of this conversion and would not use it, and they will rewrite their own. I favour using a library approach for this common functions and that's why I am wondering whether in Scalaz it exists such a feature.
It's pretty straightforward if you know the types. First implicit conversion from A to B:
implicit def conversion(a: A): B = //...
then you need implicit conversion from List[S] to List[T] where S and T are arbitrary types for which implicit conversion from S to T exists:
implicit def convList[S, T](input: List[S])(implicit c: S => T): List[T] =
input map c
This should then work:
val listOfA: List[A] = //...
val listOfB: List[B] = listOfA
which is resolved by the compiler to:
val listOfB: List[B] = convList(listOfA)(conversion)
where S is A and T is B.
I wouldn't use an implicit conversion here, but a view bound in the class:
case class Foo(x: Int)
case class Bar(y: Int)
implicit def foo2Bar(foo: Foo) = Bar(foo.x)
case class Items[A <% Bar](xs: List[A]) {
def apply(x: Int): Bar = xs(x)
}
You can now create an instance of Items with a list of Foo and internally use them, as if they were Bars.
scala> Items(List(Foo(1)))
res8: Items[Foo] = Items(List(Foo(1)))
scala> res8(0)
res9: Bar = Bar(1)
edit:
Some clarification, on why I would not use an implicit conversion:
Implicit conversions can be dangerous, when they are in scope and accidentally convert things, that they shouldn't convert. I would always convert stuff explicitly or via view bounds, because then I can control it, also implicit conversion may shrink the size of your code, but also makes it harder to understand for others. I would only use implicit conversion for the 'extend my library' pattern.
edit2:
You could however add a method to the collection types, that does this conversion, if such a method is in scope:
trait Convertable[M[A], A] {
def convertTo[B](implicit f: A => B): M[B]
}
implicit def list2Convertable[A](xs: List[A]) = new Convertable[List, A] {
def convertTo[B](implicit f: A => B) = xs.map(f)
}
scala> implicit def int2String(x: Int) = x.toString
int2String: (x: Int)String
scala> List(1,2,3).convertTo[String]
res0: List[String] = List(1, 2, 3)
Instead of using another implicit conversion here, I would probably use a typeclass instead, but I think you get the basic idea.
Works starting with Scala 2.10:
implicit class ListOf[A](val list: List[A]) {
def of[B](implicit f: A => B): List[B] = list map f
}
implicit def int2String(i: Int) = i.toString
// Usage
List(1,2,3).of[String]
In my code, I'm using a more general version adapted from Tomasz' solution above which handles all Traversable instances
/** Implicit conversion for Traversable instances where the elements are convertable */
implicit def convTrav[S, T, I[S] <: Traversable[S]](input: I[S])(implicit c: S => T): I[T] =
(input map c).asInstanceOf[I[T]]
(This is working for me, although I'm keen to know if any more experienced Scala programmers think this is a bad idea for any reason, apart from the usual caveats about implicit conversions)

How to know if an object is an instance of a TypeTag's type?

I have a function which is able to know if an object is an instance of a Manifest's type. I would like to migrate it to a TypeTag version. The old function is the following one:
def myIsInstanceOf[T: Manifest](that: Any) =
implicitly[Manifest[T]].erasure.isInstance(that)
I have been experimenting with the TypeTags and now I have this TypeTag version:
// Involved definitions
def myInstanceToTpe[T: TypeTag](x: T) = typeOf[T]
def myIsInstanceOf[T: TypeTag, U: TypeTag](tag: TypeTag[T], that: U) =
myInstanceToTpe(that) stat_<:< tag.tpe
// Some invocation examples
class A
class B extends A
class C
myIsInstanceOf(typeTag[A], new A) /* true */
myIsInstanceOf(typeTag[A], new B) /* true */
myIsInstanceOf(typeTag[A], new C) /* false */
Is there any better way to achieve this task? Can the parameterized U be omitted, using an Any instead (just as it is done in the old function)?
If it suffices to use subtyping checks on erased types, do as Travis Brown suggested in the comment above:
def myIsInstanceOf[T: ClassTag](that: Any) =
classTag[T].runtimeClass.isInstance(that)
Otherwise you need to explicitly spell out the U type, so that scalac captures its type in a type tag:
def myIsInstanceOf[T: TypeTag, U: TypeTag] =
typeOf[U] <:< typeOf[T]
In your specific case, if you actually need to migrate existing code and keep the same behavior, you want ClassTag. Using TypeTag is more precise, but exactly because of that some code is going to behave differently, so (in general) you need to be careful.
If you indeed want TypeTag, we can do even better than the above syntax; the effect at the call site is the same as omitting U.
Recommended alternatives
Using pimping
With Eugene's answer, one has to spell both types, while it's desirable to deduce the type of that. Given a type parameter list, either all or none are specified; type currying could maybe help, but it seems simpler to just pimp the method. Let's use for this implicit classes, also new in 2.10, to define our solution in just 3 lines.
import scala.reflect.runtime.universe._
implicit class MyInstanceOf[U: TypeTag](that: U) {
def myIsInstanceOf[T: TypeTag] =
typeOf[U] <:< typeOf[T]
}
I would in fact argue that something like this, with a better name (say stat_isInstanceOf), could even belong into Predef.
Use examples:
//Support testing (copied from above)
class A
class B extends A
class C
//Examples
(new B).myIsInstanceOf[A] //true
(new B).myIsInstanceOf[C] //false
//Examples which could not work with erasure/isInstanceOf/classTag.
List(new B).myIsInstanceOf[List[A]] //true
List(new B).myIsInstanceOf[List[C]] //false
//Set is invariant:
Set(new B).myIsInstanceOf[Set[A]] //false
Set(new B).myIsInstanceOf[Set[B]] //true
//Function1[T, U] is contravariant in T:
((a: B) => 0).myIsInstanceOf[A => Int] //false
((a: A) => 0).myIsInstanceOf[A => Int] //true
((a: A) => 0).myIsInstanceOf[B => Int] //true
A more compatible syntax
If pimping is a problem because it changes the invocation syntax and you have existing code, we can try type currying (more tricky to use) as follows, so that just one type parameter has to be passed explicitly - as in your old definition with Any:
trait InstanceOfFun[T] {
def apply[U: TypeTag](that: U)(implicit t: TypeTag[T]): Boolean
}
def myIsInstanceOf[T] = new InstanceOfFun[T] {
def apply[U: TypeTag](that: U)(implicit t: TypeTag[T]) =
typeOf[U] <:< typeOf[T]
}
myIsInstanceOf[List[A]](List(new B)) //true
If you want to learn to write such code yourself, you might be interested in the discussion of variations shown below.
Other variations and failed attempts
The above definition can be made more compact with structural types:
scala> def myIsInstanceOf[T] = new { //[T: TypeTag] does not give the expected invocation syntax
def apply[U: TypeTag](that: U)(implicit t: TypeTag[T]) =
typeOf[U] <:< typeOf[T]
}
myIsInstanceOf: [T]=> Object{def apply[U](that: U)(implicit evidence$1: reflect.runtime.universe.TypeTag[U],implicit t: reflect.runtime.universe.TypeTag[T]): Boolean}
Using structural types is however not always a good idea, as -feature warns:
scala> myIsInstanceOf[List[A]](List(new B))
<console>:14: warning: reflective access of structural type member method apply should be enabled
by making the implicit value language.reflectiveCalls visible.
This can be achieved by adding the import clause 'import language.reflectiveCalls'
or by setting the compiler option -language:reflectiveCalls.
See the Scala docs for value scala.language.reflectiveCalls for a discussion
why the feature should be explicitly enabled.
myIsInstanceOf[List[A]](List(new B))
^
res3: Boolean = true
The problem is the slowdown due to reflection, required to implement structural types. Fixing it is easy, just makes the code a bit longer, as seen above.
A pitfall I had to avoid
In the above code, I write [T] instead of [T: TypeTag], my first attempt. It is interesting why it fails. To understand that, take a look:
scala> def myIsInstanceOf[T: TypeTag] = new {
| def apply[U: TypeTag](that: U) =
| typeOf[U] <:< typeOf[T]
| }
myIsInstanceOf: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])Object{def apply[U](that: U)(implicit evidence$2: reflect.runtime.universe.TypeTag[U]): Boolean}
If you look carefully at the type of the return value, you can see it's implicit TypeTag[T] => U => implicit TypeTag[U] (in pseudo-Scala notation). When you pass an argument, Scala will think it's for the first parameter list, the implicit one:
scala> myIsInstanceOf[List[A]](List(new B))
<console>:19: error: type mismatch;
found : List[B]
required: reflect.runtime.universe.TypeTag[List[A]]
myIsInstanceOf[List[A]](List(new B))
^
A tip
Last and least, one tip which might or not interest you: in this attempt, you are passing TypeTag[T] twice - hence you should remove : TypeTag after [T.
def myIsInstanceOf[T: TypeTag, U: TypeTag](tag: TypeTag[T], that: U) =
myInstanceToTpe(that) stat_<:< tag.tpe
I used the above suggestions to come up with the following. Feedback is welcomed.
/*
Attempting to cast Any to a Type of T, using TypeTag
http://stackoverflow.com/questions/11628379/how-to-know-if-an-object-is-an-instance-of-a-typetags-type
*/
protected def toOptInstance[T: ClassTag](any: Any) =
classTag[T].runtimeClass.isInstance(any) match {
case true =>
Try(any.asInstanceOf[T]).toOption
case false =>
/*
Allow only primitive casting
*/
if (classTag[T].runtimeClass.isPrimitive)
any match {
case u: Unit =>
castIfCaonical[T](u, "void")
case z: Boolean =>
castIfCaonical[T](z, "boolean")
case b: Byte =>
castIfCaonical[T](b, "byte")
case c: Char =>
castIfCaonical[T](c, "char")
case s: Short =>
castIfCaonical[T](s, "short")
case i: Int =>
castIfCaonical[T](i, "int")
case j: Long =>
castIfCaonical[T](j, "long")
case f: Float =>
castIfCaonical[T](f, "float")
case d: Double =>
castIfCaonical[T](d, "double")
case _ =>
None
}
else None
}
protected def castIfCaonical[T: ClassTag](value: AnyVal, canonicalName: String): Option[T] ={
val trueName = classTag[T].runtimeClass.getCanonicalName
if ( trueName == canonicalName)
Try(value.asInstanceOf[T]).toOption
else None
}
You can also capture type from TypeTag (into type alias), but only if it's not erased, so it will not work inside function:
How to capture T from TypeTag[T] or any other generic in scala?

Reader Monad with Scalaz

I try to define the Reader monad with scalaz like this:
import scalaz._
import Scalaz._
final class Reader[E,A](private[Reader] val runReader: E => A)
object Reader {
def apply[E,A](f: E => A) = new Reader[E,A](f)
def env[E]: Reader[E,E] = Reader(identity _)
implicit def ReaderMonad[E] = new Monad[PartialApply1Of2[Reader,E]#Apply] {
def pure[A](a: => A) = Reader(_ => a)
def bind[A,B](m: Reader[E,A], k: A => Reader[E,B]) =
Reader(e => k(m.runReader(e)).runReader(e))
}
}
object Test {
import Reader._
class Env(val s: String)
def post(s: String): Reader[Env, Option[String]] =
env >>= (e => if (e.s == s) some(s).pure else none.pure)
}
but I get a compiler error:
reader.scala:27: reassignment to val
env >>= (e => if (e.s == s) some(s).pure else none.pure)
^
Why is that?
Thanks,
Levi
This error is fairly opaque, even by Scala's standards. Method names ending with = are treated specially -- they are first considered as a normal identifier, and failing that, they are expanded to a self assignment.
scala> def env[A] = 0
env: [A]Int
scala> env >>= 0
<console>:7: error: reassignment to val
env >>= 0
^
scala> env = env >> 0
<console>:6: error: reassignment to val
env = env >> 0
^
If you're confused about the syntactic interpretation of your program, it's a good idea to run scalac -Xprint:parser to see what's going on. Similarly, you can use -Xprint:typer or -Xprint:jvm to see later phases of the program transformation.
So, how do you call >>= on your Reader? First of all, you'll need to explicitly pass the type argument Env to env. The resulting Reader[Env, Env] must then be converted to a MA[M[_], A]. For simple type constructors, the implicit conversion MAs#ma will suffice. However the two param type constructor Reader must be partially applied -- this means it can't be inferred and instead you must provide a specific implicit conversion.
The situation would be vastly improved if Adriaan ever finds a spare afternoon to implement higher-order unification for type constructor inference. :)
Until then, here's your code. A few more comments are inline.
import scalaz._
import Scalaz._
final class Reader[E, A](private[Reader] val runReader: E => A)
object Reader {
def apply[E, A](f: E => A) = new Reader[E, A](f)
def env[E]: Reader[E, E] = Reader(identity _)
implicit def ReaderMonad[E]: Monad[PartialApply1Of2[Reader, E]#Apply] = new Monad[PartialApply1Of2[Reader, E]#Apply] {
def pure[A](a: => A) = Reader(_ => a)
def bind[A, B](m: Reader[E, A], k: A => Reader[E, B]) =
Reader(e => k(m.runReader(e)).runReader(e))
}
// No Higher Order Unification in Scala, so we need partially applied type constructors cannot be inferred.
// That's the main reason for defining function in Scalaz on MA, we can create one implicit conversion
// to extract the partially applied type constructor in the type parameter `M` of `MA[M[_], A]`.
//
// I'm in the habit of explicitly annotating the return types of implicit defs, it's not strictly necessary
// but there are a few corner cases it pays to avoid.
implicit def ReaderMA[E, A](r: Reader[E, A]): MA[PartialApply1Of2[Reader, E]#Apply, A] = ma[PartialApply1Of2[Reader, E]#Apply, A](r)
}
object Test {
import Reader._
class Env(val s: String)
def post(s: String): Reader[Env, Option[String]] =
// Need to pass the type arg `Env` explicitly here.
env[Env] >>= {e =>
// Intermediate value and type annotation not needed, just here for clarity.
val o: Option[String] = (e.s === s).guard[Option](s)
// Again, the partially applied type constructor can't be inferred, so we have to explicitly pass it.
o.pure[PartialApply1Of2[Reader, Env]#Apply]
}
}