I'm trying to use a code similar to
abstract class A[T] extends Ordered[A[T]] {
val att:Int
def compare(that:A[T]) =
if (this.att >= that.att)
1
else
-1
}
class B extends A[Int] {
val att = 1
}
When I try this in Scala 2.11 REPL
scala> import scala.collection.immutable.SortedSet
scala> SortedSet[B]()
I get the following error
<console>:11: error: diverging implicit expansion for type Ordering[B]
starting with method ordered in trait LowPriorityOrderingImplicits
SortedSet[B]()
How can I solve this?
You need an instance of the Ordering type class to create a SortedList. The ordered method mentioned in the error message will automatically create an Ordering[X] for any type X that's an Ordered[X].
Your B is not an Ordered[B], however—it only extends Ordered[A[Int]]. Ordered is invariant in its type argument, so Ordered[B] and Ordered[A[Int]] have essentially nothing to do with each other.
You can address this issue with F-bounded polymorphism:
abstract class A[T, S <: A[T, S]] extends Ordered[S] {
val att: Int
def compare(that: S)=
if (this.att >= that.att)
1
else
-1
}
class B extends A[Int, B] {
val att = 1
}
Now B extends Ordered[B] and you can create the sorted set.
Alternatively, you could use your original code and just create a SortedSet[A[Int]]. It's a much better idea to avoid Ordered altogether, though, and just define the Ordering type class instance directly.
Related
Scala version: 2.12.4.
Let's say, there's one empty trait and one class with function, which accepts trait instance as implicit parameter:
trait I
class A {
def fa()(implicit i: I): Unit = {}
}
Let's define another class, which invokes this fa() function. We'll try to import I instance from its companion object:
class B(a: A) {
import B._
def fb(): Unit = { a.fa() }
}
object B {
private implicit object II extends I
}
But we face an error then!
error: could not find implicit value for parameter i: I
def fb(): Unit = { a.fa() }
^
Let's make implicit val then in class B:
class B(a: A) {
import B._
private implicit val ii = II
def fb(): Unit = { a.fa() }
}
Suddenly, we still face an error anyway:
error: ambiguous implicit values:
both value ii in class B of type => B.II.type
and object II in object B of type B.II.type
match expected type I
def fb(): Unit = { a.fa() }
^
Compiler doesn't see implicit in the first case, but sees the same implicit in the second case. Why?
How to import this implicit object from companion object?
This is an ordering issue with type inference. There are other similar questions, I don't know if there is an exact duplicate.
The issue is that when class B is type-checked, type inference hasn't yet run on object B. Using II in the body of class B in the second example triggers this type inference and makes it visible as an implicit I.
It can be solved by either placing the companion object before the class, or by giving explicit type to II, e.g.
object B {
private implicit val II: I = new I {}
}
See e.g. Why does this explicit call of a Scala method allow it to be implicitly resolved?
I am trying to get hold of a shapeless Generic for a case class with a marker trait, like this:
case class X(a:String)
trait UniversalTrait extends Any {}
object MyApp extends App {
val ok = Generic[X]
val notOk = Generic[X with UniversalTrait]
}
It doesn't compile, with error could not find implicit value for parameter gen: shapeless.Generic[X with UniversalTrait] in the notOk line. Why is that? And can something be done?
Side note: I thought that it might be something to do with from not being able to add the marker trait to the returned instance, so I attempted fixing things by adding this:
object UniversalTrait {
implicit def genGeneric[P1<:Product with UniversalTrait,P2<:Product,L<:HList]
(implicit constraint: P1 =:= P2 with UniversalTrait,
underlying: Generic.Aux[P2,L]): Generic.Aux[P1,L] = new Generic[P1]{
type Repr=L
def to(t: P1): Repr = underlying.to(t)
def from(r: Repr): P1 = underlying.from(r).asInstanceOf[P1]
}
}
However, the error remains.
Deriving works for algebraic data types only.
That is a (sealed) trait and case classes (objects) extending the trait.
case class X(a:String) extends UniversalTrait
sealed trait UniversalTrait extends Any {}
val ok = Generic[X]
I'm trying to implement a few structures from Okasaki's book in Scala, and in tests try to keep the actual tests in the base class, only using subclasses to provide the instance-under-test.
For example, a test for unbalanced (tree) set looks as follows:
class UnbalancedSetSpec
extends SetSpec(new UnbalancedSet[Int])
with IntElements
where
abstract class SetSpec[E, S](val set: Set[E, S]) extends Specification with ScalaCheck {
implicit def elements: Arbitrary[E]
// ...
private def setFrom(es: Seq[E]): S = es.foldRight(set.empty)(set.insert)
}
Now sometimes I want to specialise the child spec, e.g.
class RedBlackSetSpec
extends SetSpec(new RedBlackSet[Int])
with IntElements {
"fromOrdList" should {
"be balanced" ! prop { (a: List[Int]) =>
val s = RedBlackSet.fromOrdList(a.sorted)
set.isValid(s) should beTrue
}
}
}
it fails because there's no method isValid on Set[E, S] — it's defined in RedBlackSet[E]. But if I go ahead and change SetSpec[E, S](val set: Set[E, S]) to SetSpec[E, S, SES <: Set[E, S]](val set: SES), this particular problem disappears, but the code still fails to compile:
Error:(7, 11) inferred type arguments [Nothing,Nothing,okasaki.RedBlackSet[Int]] do not conform to class SetSpec's type parameter bounds [E,S,SES <: okasaki.Set[E,S]]
extends SetSpec(new RedBlackSet[Int])
^
Error:(7, 11) inferred type arguments [Nothing,Nothing,okasaki.UnbalancedSet[Int]] do not conform to class SetSpec's type parameter bounds [E,S,SES <: okasaki.Set[E,S]]
extends SetSpec(new UnbalancedSet[Int])
^
The definition of RedBlackSet is as follows:
package okasaki
class RedBlackSet[E](implicit ord: Ordering[E]) extends Set[E, RBTree[E]] {
so I would expect E to be inferred as Int rather than Nothing, and S as RBTree[Int] — but it doesn't happen.
class RedBlackSetSpec
extends SetSpec[Int, RedBlackSet.RBTree[Int], RedBlackSet[Int]](new RedBlackSet[Int])
with IntElements {
and
class UnbalancedSetSpec
extends SetSpec[Int, BinaryTree[Int], UnbalancedSet[Int]](new UnbalancedSet[Int])
with IntElements
work fine, but look ugly.
I'm struggling to understand why E and S are not inferred here. Any hints?
This is actually a well-known problem with Scala type inference: it can't infer SES "first" and use it to infer E and S. One solution comes to mind:
class RedBlackSetSpec(override val set: RedBlackSet[Int]) extends SetSpec(set) with IntElements {
def this() = this(new RedBlackSet[Int])
...
}
It becomes less ugly if you make set in SetSpec an abstract val instead of a constructor argument, but with a slight tradeoff in cases you don't need to specialize. I think there should be a better one, but this should work.
The type class pattern in Scala involves defining a trait such as:
trait Show[T] {
def show(obj: T): String
}
Then you can define instantiations of this type class as such:
object Show {
implicit val string = new Show[String] {
def show(obj: String): String = obj
}
implicit object BooleanShow extends Show[Boolean] {
def show(obj: Boolean): String = obj.toString
}
}
The advantage of defining these instantiations for basic types in the companion object is that they are automatically in scope whenever the type class is concerned (roughly).
Functionally it would appear defining the instantiation as an implicit val or an implicit object does not change much.
Is there a difference? Is one way better than the other?
There is actually more than the type names between val and object.
You know, object in Scala is something like a singleton in Java.
Maybe you thought that both string and BooleanShow are in an object not a class so they have no difference, but that's not true.
They are val and object no matter what.
Try this in Scala REPL.
trait Show[T] {
def show(obj: T): String
}
object Show {
println("!! Show created")
implicit val string = new Show[String] {
println("!! string created")
def show(obj: String): String = obj
}
implicit object BooleanShow extends Show[Boolean] {
println("!!BooleanShow created")
def show(obj: Boolean): String = obj.toString
}
}
If only the definition is done, then no printlns are executed afterwards, since Show is a singleton in effect. It's not created yet.
Next, execute Show in Scala REPL.
scala> Show
!! Show created
!! string created
res0: Show.type = Show$#35afff3b
You see, printlns in Show and Show.string were called, but the one in Show.BooleanShow was not.
You can execute Show.BooleanShow next in Scala REPL.
scala> Show.BooleanShow
!!BooleanShow created
res1: Show.BooleanShow.type = Show$BooleanShow$#18e419c5
Show.BooleanShow was initialized at last. It is a singleton, so it is lazy.
Basically, your question is the same as val and object inside a scala class? except that your val and object are defined in an object, but the linked question tries to find differences val and object defined in a class and the method in val uses reflection (but yours uses overriding, so no reflection is involved). implicit basically does not make difference in what they are.
I think you already know the difference between class and object. Further information can be found in the linked question.
Since they say always to use explicit types for implicits, prefer val over object.
Compare Why can't Scala find my typeclass instance defined implicitly in the companion object, when the typeclass is not in a dedicated source file? where it makes a difference.
Make it lazy if necessary.
Elaboration:
scala> trait T
defined trait T
scala> object X { implicitly[T] ; object O extends T }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; object O extends T }
^
scala> object X { implicitly[T] ; implicit object O extends T }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; implicit object O extends T }
^
scala> object X { implicitly[O.type] ; implicit object O extends T }
defined object X
scala> object X { implicitly[T] ; implicit object O extends T ; implicit def y = O }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; implicit object O extends T ; implicit def y = O }
^
scala> object X { implicitly[T] ; implicit object O extends T ; implicit def y: T = O }
defined object X
The inferred type of O is the singleton type O.type.
With val x = new X { } you are creating an anonymous subclass of X, whereas with object x extends X you create a "proper" subclass. I would think that the overhead of an object is minimal, and as #applicius points out, it has proper name. Therefore I suggest to go for the object in this case.
Given:
trait Mixin {}
case class A(a: Int) extends Mixin
case object B extends Mixin
trait Base {
val m = A(1)
}
trait Sub extends Base {
override val m = B // does. not. compute.
}
I get a compilation error in trait Sub:
<console>:18: error: overriding value m in trait Base of type A;
value m has incompatible type
override val m = B // does. not. compute.
^
Why? The case object inherits the correct trait, just like the case class does. This is Scala 2.10.
You need to make m of type Mixin:
trait Base {
val m: Mixin = A(1)
}