Can I use a view bound in a Scala value class? - scala

While dealing with some Java code, I wanted to find a way to reduce a Raw Set to include its parameterized type.
I also wanted it to work for Scala sets as well, so I did the following
implicit class Harden[S <% mutable.Set[_]](val set: S) extends AnyVal {
def cast[T] = set.map(_.asInstanceOf[T])
}
That resulted in a compiler error that I didn't expect
Error:(27, 27) field definition is not allowed in value class
implicit class Harden[S <% mutable.Set[_]](val set: S) extends AnyVal {
I didn't find any mention of this type of restriction in the Scala View Bounds or Value Class documentation.
Why is this not allowed? I'm using Scala 2.10.3.

As you can see from this sbt console output:
scala> :type implicit class Harden[S <% mutable.Set[_]](val set: S)
[S]AnyRef {
val set: S
private[this] val set: S
implicit private[this] val evidence$1: S => scala.collection.mutable.Set[_]
def <init>(set: S)(implicit evidence$1: S => scala.collection.mutable.Set[_]): Harden[S]
}
... the actual constructor of Harden desugars behind the scenes to:
def <init>(set: S)(implicit evidence$1: S => scala.collection.mutable.Set[_]): Harden[S]
... (i.e. takes set in one argument list and implicit evidence$1 in another).
As described in value classes limitations here:
must have only a primary constructor with exactly one public, val parameter whose type is not a value class.
... whitch means that Harden violaties this limitation.
You can achieve something similar, howerver. Try to convert your view bound defined on class to implicit evidence on method instead.
Something like this:
scala> implicit class Harden[S](val set: S) extends AnyVal {
| def cast[T](implicit ev: S => scala.collection.mutable.Set[_]) = set.map(_.asInstanceOf[T])
| }
defined class Harden
This will compile:
scala> Set(1,2,3).cast[Any]
res17: scala.collection.mutable.Set[Any] = Set(1, 2, 3)
And this will fail, as expected:
scala> List(1,2,3).cast[Any]
<console>:24: error: No implicit view available from List[Int] => scala.collection.mutable.Set[_].
List(1,2,3).cast[Any]
^

It is not allowed because as structured now, value classes must have exactly one parameter, but
implicit class Foo[A <% B](val a: A)
desugars to
implicit class Foo[A,B](val a: A)(implicit evidence$1: A => B)
which no longer has just a single parameter.

Related

Pimps are not working when used with generics

Consider following code (script) in which the SeqPimps can't be changed:
import scala.reflect.ClassTag
implicit class SeqPimps[T: ClassTag](s: Seq[T]) {
def indexOfOpt(e: T): Option[Int] = s.indexOf(e) match {
case -1 => None
case idx => Some(idx)
}
}
class A[T] {
val fn = (y: T) => List[T]().indexOfOpt(y)
}
object Main extends App {
val fn = (y: Int) => List[Int]().indexOfOpt(y)
println(fn(0))
println((new A[String]).fn(""))
}
Main.main(args)
It crashes with:
xxx/test.scala:11: error: value indexOfOpt is not a member of List[T]
val fn = (y: T) => List[T]().indexOfOpt(y)
^
one error found
My questions:
Why is it working when type is explicitly specified (in Main, after commenting out A and the one println it works fine) and complaining about non-existing member when generic type is used? The call looks same.
How to fix the snippet without modifying SeqPimps (e.g. removing of ClassTag - it is required by other methods in real project)?
Remember that writing class SeqPimps[T: ClassTag](s: Seq[T]) actually tells the compiler to add an implicit parameter like that: class SeqPimps[T](s: Seq[T])(implicit ev: ClassTag[T]).
The compilation fails because the implicit SeqPimps cannot be applied, and this one cannot be applied because no implicit ClassTag[T] is available from within A.
There are a couple ways you can add a ClassTag there, for example: class A[T : ClassTag] {. Where to pass that implicit ClassTag is up to you and your use case...
Oh, it turns out I was missing a ClassTag in class definition:
class A[T: ClassTag] {

Implicit class resolution for parameterized types

In the following example, it seems that the Scala compiler only recognizes an implicit class when it is defined to take the higher-kinded representation of Wrapper. Why is that?
scala> case class Nested(n: Int)
defined class Nested
scala> case class Wrapper[A <: Product](nested: A)
defined class Wrapper
scala> implicit class I1[W <: Wrapper[A], A <: Product](underlying: W) {
| def ok1() = true
| }
defined class I1
scala> Wrapper(Nested(5)).ok1()
<console>:26: error: value ok1 is not a member of Wrapper[Nested]
Wrapper(Nested(5)).ok1()
^
scala> implicit class I2[W <: Wrapper[_]](underlying: W) {
| def ok2() = true
| }
defined class I2
scala> Wrapper(Nested(5)).ok2()
res1: Boolean = true
Is there a workaround for implicit resolution that maintains full information about the nested type, allowing typeclass evidence, e.g., TypeTag, to be attached to it?
Note: the example above shows Nested and Wrapper to be case classes but that's not integral to the question. It's simply a convenience for a shorter and simpler console session.
This is happening because of a limitation in Scala's type inference. See SI-2272.
The implicit fails to resolve because the compiler cannot properly infer A. We can see this if we enable -Xlog-implicits. Notice that A is inferred as Nothing:
I1 is not a valid implicit value for Test.w.type => ?{def ok: ?} because:
inferred type arguments [Wrapper[Nested],Nothing] do not conform to method I1's type parameter bounds [W <: Wrapper[A],A <: Product]
The same thing happens if we try to instantiate I1 manually:
scala> val w = Wrapper(Nested(5))
w: Wrapper[Nested] = Wrapper(Nested(5))
scala> new I1(w)
<console>:21: error: inferred type arguments [Wrapper[Nested],Nothing] do not conform to class I1's type parameter bounds [W <: Wrapper[A],A <: Product]
new I1(w)
^
<console>:21: error: type mismatch;
found : Wrapper[Nested]
required: W
new I1(w)
^
Now, the work-arounds.
First, Wrapper is a case class, so there shouldn't be a reason for it to have sub-types. You can remove the W type parameter, and change underlying to a Wrapper[A]:
implicit class I1[A <: Product](underlying: Wrapper[A]) {
def ok = true
}
If you still wish to require two type parameters, you can also require implicit evidence that W <:< Wrapper[A], while removing the upper-bound on the type parameter W:
implicit class I1[W, A <: Product](underlying: W)(implicit ev: W <:< Wrapper[A]) {
def ok = true
}
Everything Michael said is true. Here is some extra perspective on this issue.
Because of the way you wrote your implicit class it looks like you want the implicit class to work on all subtypes of Wrapper and have as specific information about all types involved as possible. (99% of the time it's a bad idea to extend case classes, but it is possible, and these tricks also work for non case classes).
The trick basically is to make sure that all the type parameters that you want inferred are present somewhere in the value parameter lists. Another thing to keep in mind is this:
scala> trait Foo[A]; trait Bar extends Foo[Int]
defined trait Foo
defined trait Bar
scala> implicitly[Bar with Foo[Int] =:= Bar]
res0: =:=[Bar with Foo[Int],Bar] = <function1>
Take these two pieces of knowledge and you can rewrite your implicit class like this:
implicit class I1[Y, A <: Product](underlying: Y with Wrapper[A]) {
def ok1(): (Y, A) = ???
}
And see it at work:
scala> :paste
// Entering paste mode (ctrl-D to finish)
case class Nested(n: Int)
case class Wrapper[A <: Product](nested: A)
class Crazy(override val nested: Nested) extends Wrapper[Nested](nested)
implicit class I1[Y, A <: Product](underlying: Y with Wrapper[A]) {
def ok1(): (Y, A) = ???
}
// Exiting paste mode, now interpreting.
scala> :type Wrapper(Nested(5)).ok1()
(Wrapper[Nested], Nested)
scala> :type new Crazy(Nested(5)).ok1()
(Crazy, Nested)
Note that the last solution Michael gave is based on the same thing: by moving the upper bound to the implicit parameter list, A is now present in the value parameter lists and can be inferred by the compiler.

How to specify required function on generic selector in Scala

I know this can be done but I can't remember (or locate) the syntax for the life of me. How can I specify that a specific function must be present on a generic type in a function definition?
For instance, I know I can do this:
def blah[A](p: A)
What I really want is something like this (but my syntax is all wrong of course):
def blah[A(someFunction)](p: A)
I am not sure if using this is a good idea, but here is how it works:
def blah[A <: { def someFunction: String }](a: A) : Unit =
println(a.someFunction)
scala> class Test { def someFunction: String = "hello" }
defined class Test
scala> blah(new Test)
hello
scala> class Test2
defined class Test2
scala> blah(new Test2)
<console>:16: error: inferred type arguments [Test2] do not conform to method blah's type parameter bounds [A <: AnyRef{def someFunction: String}]
Note that this feature (so-called structural types) uses reflection, and has to be enabled using the language import import scala.language.reflectiveCalls
What you're looking for is called a "structural type".
Any example from here: https://twitter.github.io/scala_school/advanced-types.html
scala> def foo(x: { def get: Int }) = 123 + x.get
foo: (x: AnyRef{def get: Int})Int
scala> foo(new { def get = 10 })
res0: Int = 133
Note, however, that this is going to be slower than just declaring a trait that requiring that any argument implements that trait.

Implicit not found when omitting empty argument list

I have the following (simplified) code:
case class Value[T](value: T)
trait Absable[In,Out] {
def absoluteValue(in: In): Out
}
implicit class AbsValue[In, Out](in: Value[In]) {
def abs()(implicit ev: Absable[In, Out]): Value[Out] = Value(ev.absoluteValue(in.value))
}
implicit def AbsNumeric[A : Numeric] = new Absable[A, A] {
def absoluteValue(in: A) = implicitly[Numeric[A]].abs(in)
}
Now I want to use the abs function on a Value:
scala> Value(-3).abs()
res3: Value[Int] = Value(3)
scala> Value(-3).abs
<console>:14: error: could not find implicit value for parameter ev: Absable[Int,Nothing]
Value(-3).abs
^
I added an empty argument list in front of the implicit arguments to give callers more flexibility, but now when I omit the empty list at the call site the compiler can't find the implicit... So now instead of more flexibility callers get confusing compile errors.
I don't understand how leaving off the argument list can affect the type inference or implicit resolution.
I am using scala 2.11.6

Implicit conversion of a generic container for an implicit parameter in Scala

Is there a way to make this work? (Scala 2.8.1)
class A
def f(implicit a: A) = 0
class Vendor[T](val v: T)
implicit val vendor = new Vendor(new A)
implicit def vendorToVal[T](implicit v: Vendor[T]) = v.v
f
The error is: 'diverging implicit expansion for type A starting with method vendorToVal'
This is related to Lift 2.2 dependency injection, the real code looks like this:
class UserStore(implicit db: DbAccess)
object DependencyFactory extends Factory {
implicit val db = new FactoryMaker[DbAccess](Model) {}
import db._ // implicit conversion would allow to remove this import
implicit val userStore = new FactoryMaker[UserStore](new UserStore) {}
}
This question is related to: Is there a way to implicitly convert an implicit parameter in Scala?
The problem is caused with vendorToVal method - I observed the same behavior many times, when I've been using implicit parameters in implicit type-parametrized methods. Unfortunately, I've found no simple and elegant glue in 2.8._.
Some interesting threads, related to the topic:
http://scala-programming-language.1934581.n4.nabble.com/scala-Why-is-this-a-diverging-implicit-td1998156.html
http://www.scala-lang.org/node/6847
In Scala 2.9 trunk, you can do this:
scala> class A
defined class A
scala> def f(implicit a: A) = 0
f: (implicit a: A)Int
scala>
scala> class Vendor[T](val v: T)
defined class Vendor
scala> implicit def value[T: Vendor] = implicitly[Vendor[T]].v
value: [T](implicit evidence$1: Vendor[T])T
scala> implicit val vendor = new Vendor(new A)
vendor: Vendor[A] = Vendor#bbb2d0
scala> f
res0: Int = 0
Calling f will search for a value of type A, and find the implicit value[A], which requires an evidence parameter of type Vendor[A]. It resolves this evidence parameter to vendor.
I don't think implicits were that powerful in 2.8.1.