Order of definition matters in Scala? - scala

When looking for implicits, the Scala compiler looks, among other places, in the companion object of the various parts of the classes involved. Apparently, though, it fails to perform this lookup when the implicit conversion is used in the class itself, if it is defined before the companion object. The minimal example I was able to cook up is:
trait Counter[A] {
def count(a: A): Int
}
object Foo {
def foo[A](a: A)(implicit c: Counter[A]) = c.count(a)
}
case class Bar(id: Int) {
import Foo._
def count = foo(this)
}
object Bar {
implicit object BarCounter extends Counter[Bar] {
def count(b: Bar) = b.id
}
}
This fails to compile saying could not find implicit value for parameter c: Counter[Bar] - I am using Scala 2.9.1.
The interesting thing (suggested by rjsvaljean) is that if we invert the order - that is, we define object Bar before case class Bar - verything compiles fine.
Is this a compiler bug? Or I am missing something about the scope rules of Scala?
I should also mention that this problem only arises with implicit resolution. If we explicitly pass the BarCounter object, everything compiles fine.

It seems to be an actual compiler bug. I have posted it here.

Related

Achieving covariant return types on type level in presence of a non-finitary class graph

Imagine a pretty ordinary piece of code:
trait Template[X, +T] {
def m :T
}
trait Root[X] extends Template[X, Wrap[X]] {
override def m = new Wrap[X]
}
trait Sub[X] extends Root[X] with Template[X, Wrap2[X]] {
override def m = new Wrap2[X]
}
trait Wrap[X] extends Root[Option[X]]
trait Wrap2[X] extends Sub[X]
Root is a base class of a class hierarchy which happens to have method m the return type of which is occasionally narrowed by subclasses, as per Sub. An additional requirement is that I need that return type encoded somehow in the type of any C <: Root[_], so I can generalize over it. This is done through trait Template: I can in my implicits declare type parameters [X, T, W <: Template[X, T]] (forget for now problems with type inference here).
The problem is, the code above does not compile - the class graph is non-finitary. It is because:
Root[X] <: Template[X, Wrap[X]] <: Template[X, Root[Option[X]]]
For reasons unbeknownst to me, it is a good idea to expand the last type in the compiler by substituting Root[Option[X]] recursively with X. Now, if someone can explain why eager expanding of the subtype relation is done here, and not in Root[X] <: Template[X, Root[X]], for example, it would be great to know, but is not my main question here. Which is: how to refactor it?
I see two options:
1.
trait Template[X, +T[_]] {
def m :T[X]
}
This won't work, because the kind of the return type is not always the same: even adding a bound on a type parameter will break it.
The second alternative, are of course, member types:
trait Root[X] {
type Result <: Wrap[X]
def m :Wrap[X]
}
trait Sub[X] extends Root[Option[X]] {
type Result <: Wrap2[X]
}
But member types come always with one huge problem: the only possible way of achieving covariance is by declaring the return type Result as an upper bound. However, in that case, I cannot implement method m within that class in any other way than throwing an exception, because Result is unknown in that place. If I want to keep the hierarchy open for extension, for every interface trait I have to have a separate implementation class, i.e.
class RootImpl[X] extends Root[X] {
override type Result = Wrap[X]
override def m = new Wrap[X]
}
class SubImpl[X] extends Sub[X] {
override type Result = Wrap2[X]
override def m = new Wrap2[X]
}
Even if I extract the above bodies to mix in traits, so I don't have to cut and paste the implementation in every Root subclass which would like to use the default implementation,
it is still quite inconvenient compared to having the implementation within the actual interface traits.
Is there anything I didn't think of?
Would something like this work?
sealed trait Template[X, +T] {
def m(implicit ops: TemplateOps[X, T]): T = ops.m
}
sealed trait TemplateOps[X, +T] {
def m: T
}
object TemplateOps {
implicit def rootOps[X] = new TemplateOps[X, Option[X]] {
def m: Option[X] = ???
}
implicit def subOps[X] = new TemplateOps[X, X] {
def m: X = ???
}
}
class Root[T] extends Template [T,Option[T]
class Sub[T] extends Template [T,T]
Well, I have since thought of and tried another solution, so I thought I'd answer my question for posterity. It doesn't solve my real issue well, so I won't accept it though, but more on that later.
What I forgot, because as most people I do not really use structural types as I view them as a shabby solution, this actually might be a sensible, minimalistic application for them. Scala allows to refine a type not only by specifying its member types, but also methods (and values). We could get rid of Template completely and use plain hardcoded covariance:
trait BaseSignature {
def m :Any
}
trait Root[X] extends BaseSignature {
override def m = new Wrap[X]
}
trait Sub[X] extends Root[X] {
override def m = new Wrap2[X]
}
We simply use the whole signature of method m, including its return type, as part of a type we are interested in. A simplest example would be:
def wrap[R](x :BaseSignature { def m :R }) :X = x.m
wrap(new Root[Int]) //:Wrap1[X]
wrap(new Sub[Int]) //:Wrap2[X]
What's important to note, is that x.m call there is not reflective, as m method itself is declared in BaseSignature - scala compiler calls simply that and does a no-op cast to R. BaseSignature is necessary because of scala's annoying rule that an implemented method always overrides a declaration, even from the point of view of the caller,
so an argument of x :Root[X] { def m :R } would have x.m :Wrap1[X] and there is no way around it AFAIK.
This solution even works for reasonably complex method signatures, including generic methods with their own type parameters with bounds, as well as using type parameters of the enclosing class. Type inference in the latter case has serious issues though. Unfortunately, and I did not realise it until I coded the simpler methods, there is a problem with return types of higher kinds which depend on type arguments, or worse, on member types of value arguments. Consider instead:
trait Root[X] {
def m[A] = new Wrap1[A]
}
trait Sub[X] {
def m[A] = new Wrap3[A, X]
}
trait Wrap3[A, B]
The return type which we must infer here is a type constructor, and Scala 2 is very bad at that: it would infer R in m[A] :R[A] no problem in the first case, but in the case of Wrap2 only if A is the last argument, so, while simple cases might be covered, it is not a robust, generic solution. From what I read, Scala 3 could infer correctly R[A] =:= [A]Wrap3[X, A], so it might be good in the future.
For now, I would need to define an external type alias which guides the inferer:
trait Sub[X] extends Root[X] {
type SubResult[A] = Wrap3[X, A]
override def m[A] :SubResult[A] = new Wrap3[A]
}
Not ideal, but still better then the member type solution described earlier, as in this case any subclass Sub2 of Sub would just define its own type type Sub2Result[A] = ..., posing no conflict.
I might still stick with this as it looks like migration to Scala 3 will be the easiest, at the same time producing the simplest solution. It's still an interesting problem though, so I certainly would like to hear alternatives.

Scala Type Classes Best Practices

I'm reading through and working my way through using type classes and I came across this way of defining type classes from the Shapeless guide:
So here goes the example:
object CsvEncoder {
// "Summoner" method
def apply[A](implicit enc: CsvEncoder[A]): CsvEncoder[A] =
enc
// "Constructor" method
def instance[A](func: A => List[String]): CsvEncoder[A] =
new CsvEncoder[A] {
def encode(value: A): List[String] =
func(value)
}
// Globally visible type class instances
}
What I do not understand is the need for the apply method? What is it doing in this context above?
Later on, the guide describes how I could create a type class instance:
implicit val booleanEncoder: CsvEncoder[Boolean] =
new CsvEncoder[Boolean] {
def encode(b: Boolean): List[String] =
if(b) List("yes") else List("no")
}
is actually shortened to:
implicit val booleanEncoder: CsvEncoder[Boolean] =
instance(b => if(b) List("yes") else List("no"))
So my question now is, how does this work? What I do not get is the need for the apply method?
EDIT: I came across a blog post that describes the steps in creating type classes as below:
Define typeclass contract trait Foo.
Define a companion object Foo with a helper method apply that acts like implicitly, and a way of defining Foo instances typically from a function.
Define FooOps class that defines unary or binary operators.
Define FooSyntax trait that implicitly provides FooOps from a Foo instance.
So what is the deal with point number 2, 3 and 4?
Most of those practices came from Haskell (basically an intention to mimic Haskell's type-classes is a reason for so much boilerplate), some of it is just for convenience. So,
2) As #Alexey Romanov mentioned, companion object with apply is just for convenience, so instead of implicitly[CsvEncoder[IceCream]] you could write just CsvEncoder[IceCream] (aka CsvEncoder.apply[IceCream]()), which will return you a required type-class instance.
3) FooOps provides convenience methods for DSLs. For instance you could have something like:
trait Semigroup[A] {
...
def append(a: A, b: A)
}
import implicits._ //you should import actual instances for `Semigroup[Int]` etc.
implicitly[Semigroup[Int]].append(2,2)
But sometimes it's inconvenient to call append(2,2) method, so it's a good practice to provide a symbolic alias:
trait Ops[A] {
def typeClassInstance: Semigroup[A]
def self: A
def |+|(y: A): A = typeClassInstance.append(self, y)
}
trait ToSemigroupOps {
implicit def toSemigroupOps[A](target: A)(implicit tc: Semigroup[A]): Ops[A] = new Ops[A] {
val self = target
val typeClassInstance = tc
}
}
object SemiSyntax extends ToSemigroupOps
4) You can use it as follows:
import SemiSyntax._
import implicits._ //you should also import actual instances for `Semigroup[Int]` etc.
2 |+| 2
If you wonder why so much boilerplate, and why scala's implicit class syntax doesn't provide this functionality from scratch - the answer is that implicit class actually provides a way to create DSL's - it's just less powerful - it's (subjectively) harder to provide operation aliases, deal with more complex dispatching (when required) etc.
However, there is a macro solution that generates boilerplate automatically for you: https://github.com/mpilquist/simulacrum.
One another important point about your CsvEncoder example is that instance is convenience method for creating type-class instances, but apply is a shortcut for "summoning" (requiring) those instances. So, first one is for library extender (a way to implement interface), another one is for a user (a way to call a particular operation provided for that interface).
Another thing to note is that in shapeless the apply method is not only for cuter syntax.
Take for instance this simplified version of shapeless' Generic and some case class Foo.
trait Generic[T] {
type Repr
}
object Generic {
def apply[T](implicit gen: Generic[T]): Generic[T] { type Repr = gen.Repr } = gen
/* lots of macros to generate implicit instances omitted */
}
case class Foo(a: Int, b: String)
Now when I call Generic[Foo] I will get an instance that is typed as Generic[Foo] { type Repr = Int :: String :: HNil }. But if I call implicitly[Generic[Foo]] all the compiler knows about the result is that it's a Generic[Foo]. In other words: the concrete type of Repr is lost and I can't do anything useful with it. The reason is that implicitly is implemented as follows:
def implicitly[T](implicit e: T): T = e
That method declaration basically says: if you ask for a T I promise to give you a T, if I find one, and nothing more. So that means you'd have to ask implicitly[Generic[Foo] { type Repr = Int :: String :: HNil }] and that defeats the purpose of having automatic derivation.
Quoting the guide immediately after the object CsvEncoder definition:
The apply method ... allows us to summon a type class instance given a target type:
CsvEncoder[IceCream]
// res9: CsvEncoder[IceCream] = ...

Retrieve generic trait parameter on concrete inheritor via macro

I have a simple subtyping relation that I've set up as follows:
trait Foo[T] {
def a: Int
def b: String
def c: T
}
object Bar extends Foo[C] { /* implementation */ }
object Quux extends Foo[D] { /* implementation */ }
// ...
where C and D are concrete types. I also have a manager object that registers objects of type Foo[T] and needs to maintain generic type information in order to correctly call method c.
The scala compiler seems incapable of correctly inferring types here for my manager's register method, so I need to specify that manually. I.e., I can't do
Manager register Bar
but instead have to provide
Manager register[C, Bar.type] Bar
To make this a bit prettier, I'm writing a macro that does this automatically, but I'm stuck on retrieving the concrete type parameter of the trait the object inherits from. The basic form of the macro looks like this:
def macro_impl[T: c.WeakTypeTag](c: whitebox.Context)(a: c.Expr[T]): c.Expr[Unit] = {
import c.universe._
val typeIWant = weakTypeOf[T].???
c.Expr[Unit](q"com.example.Manager.register[${a.actualType}, ${typeIWant}]($a)")
}
I've been able to retrieve the list of supertypes of T, but I haven't been able to figure out how to get the type parameter for those types within the object declaration, i.e. I'm looking for U here: object ... extends Foo[U]). Is there a way to do this?
Edit: I can get the type information I want to show up in the console via reflection:
scala> typeOf[Bar].typeSymbol.info
res1: reflect.runtime.universe.Type =
com.example.Foo[com.example.C] {
def <init>(): com.example.Bar
def a: scala.Int
def b: String
def c(event: com.example.C): scala.Unit
}
but I'm still not sure how to get information about the com.example.Foo[com.example.C] part of the signature. Not finding anything pertinent in the reflection API docs (particularly TypeApi) about how to do this.

Providing multiple instances of same implicit specialized with different type parameters

Having an implicit instance implementation which perfectly fits for multiple types I need to provide a module with concrete instances for specific types. Following is something similar to my attempt to achieve this in the spirit of "Cake Pattern".
trait Show[ a ]{
def show( a: a ): String
}
trait PrimitiveShowInstance[ a ] {
implicit def primitiveShowInstance = new Show[ a ] {
def show( a: a ) = a.toString
}
}
object SomeModule
extends PrimitiveShowInstance[ Int ]
with PrimitiveShowInstance[ String ]
with PrimitiveShowInstance[ Boolean ]
The above code fails to compile complaining about inheriting the same trait twice. This is obviously just an example and in real case the signature of implicit conversion is quite more involved - it includes other implicits and plenty of type parameters. So introducing an "alias" method is not an option, since due to Scala's syntactic inabilities I'll still have to copy-paste the method signature.
How to solve this issue?
In this situation what you're really experiencing is an issue with type erasure. What you really want to do is the following:
object SomeModule{
implicit val primInt = new Show[Int}{
def show(a: Int) = a toString ()
}
//and so on for each "A"
}
Wherein you make sure that you always include include SomeModule._ so that the implicits are in scope. That allows you to forgoe the need to even have the implicit def primiteShowInstance method in your PrimitiveShowInstance trait.
One of the ways people get around exactly what you're seeing is just the rather vulgar:
trait SomeFoo{
self: WithIntFoo with WithDoubleFoo =>
}
and so on. Yes, ugly. Yes, sometimes less than wonderful. However, this will get around the problem of type erause and implementing the same trait several times over.
Following is a solution which allows to write the implementation of primitiveShowInstance only once, that's why it scales perfectly for more involved cases. The idea is pretty simple: we introduce another implicit, which only serves as an evidence of support for primitiveShowInstance implementation by a certain type.
trait Show[ a ]{
def show( a: a ): String
}
trait PrimitiveShowInstance {
implicit def primitiveShowInstance[ a ]( implicit support: Support[ a ] ) =
new Show[ a ] {
def show( a: a ) = a.toString
}
// Simply an evidence of support for this by type `value`.
class Support[ value ]
}
object SomeModule extends PrimitiveShowInstance {
implicit val intPrimitiveShowInstanceSupport = new Support[Int]
implicit val stringPrimitiveShowInstanceSupport = new Support[String]
}

How do I use a structural type with generic parameters?

I have two case classes
case class StringCaseClass(argument: String)
case class IntCaseClass(argument: Int)
I want to define a structural type which will match the companion object of both of these
type HasApply1 {
def apply[A, R](argument: A): R
}
This will compile fine, but when I try to use it like this
def method(caseClass: HasApply1) {
// whatever
}
method(StringCaseClass)
I will get a compiler error
found : StringCaseClass.type
required: WithApply1
(which expands to) AnyRef{def apply[A, R](string: A): R}
Is there any way of accomplishing this? If I redefine the structural type to have concrete types for A and R it will compile correctly, but then I lose the flexiblity
#aloiscochard's comment is almost there. What he forgot to mention is that case class companion objects already implement the appropriate FunctionN trait, so you can simply do this,
scala> case class StringCaseClass(argument: String)
defined class StringCaseClass
scala> case class IntCaseClass(argument: Int)
defined class IntCaseClass
scala> def method[A, R](caseClass: A => R, a: A) = caseClass(a)
method: [A, R](caseClass: A => R, a: A)R
scala> method(StringCaseClass, "foo")
res0: StringCaseClass = StringCaseClass(foo)
scala> method(IntCaseClass, 23)
res1: IntCaseClass = IntCaseClass(23)
In general you should avoid structural typing as it's very expensive. The call will be converted into a reflection call because of limitations in the JVM. When you start using scala 2.10 structural types will result in a warning at compile time (though you could disable that using a flag).
If you're looking into a more general way to add functionality to classes that don't share an inheritance hierarchy you could use Type Classes.
Here's a quick example:
trait CanCreateRFromA[A,R]{
def createNew(a:A): R
}
implicit object CanCreateBlahFromInt extends CanCreateRFromA[Int,Blah2]{
def createNew(i:Int):Blah2 = new Blah2(i)
}
implicit object CanCreateBlah1FromString extends CanCreateRFromA[String,Blah1]{
def createNew(s:String):Blah1 = new Blah1(s)
}
case class Blah1(something:String)
case class Blah2(something:Int)
def createRFromA[A,R](a:A)(implicit tc:CanCreateRFromA[A,R])= tc.createNew(a)
Then you can call:
createRFromA(1) // This gives a Blah2
createRFromA("1") // This gives a Blah1
Again I'm not sure what you're trying to accomplish, but it probably is possible to do what you want with a type class and it will be much faster.
You didn't pass an instance of StringCaseClass to your method. What you passed there is companion object of StringCaseClass (which is automatically generated for case classes).
Try if this works: method(StringCaseClass("dummy")).