Generics re: Scala.math.Ordering wrapper instance for java.lang.Comparable - scala

I want to make a simple Scala.math.Ordering wrapper instance for java.lang.Comparable. I would think this is standard, but I don't see anything similar in JavaConversions.
Can someone get something like this to work:
object ComparableOrdering[A <: Comparable[A]] extends Ordering[A] {
def compare(a: A, b: A): Int = a.compareTo(b)
}
Actually to handle classes like
interface A {}
class B implements A, Comparable<A> {}
it should be more like:
object ComparableOrdering[A <: Comparable[B] with B] extends Ordering[A] {
def compare(a: A, b: A): Int = a.compareTo(b)
}
Can anyone get this working?

The standard library already provides these instances via Ordering.ordered. For example, if you have a class like this:
class Foo(val i: Int) extends Comparable[Foo] {
def compareTo(that: Foo): Int = this.i - that.i
}
You'll automatically have an instance available:
scala> Ordering[Foo].lt(new Foo(0), new Foo(1))
res0: Boolean = true
The signature of Ordering.ordered isn't quite the same as yours:
implicit def ordered[A](implicit arg0: (A) => Comparable[A]): Ordering[A]
This works because the standard library provides implicit "conversion" functions that will up-cast any type to any of its supertypes.
If for some reason you wanted to define your own instances, you could do something like this:
implicit def comparableOrdering[A <: Comparable[A]]: Ordering[A] =
new Ordering[A] {
def compare(a: A, b: A): Int = {
println("Using custom instance for Comparable things")
a.compareTo(b)
}
}
And then:
scala> Ordering[Foo].lt(new Foo(0), new Foo(1))
Using custom instance for Comparable things
res0: Boolean = true
I'd guess that the standard library doesn't define these instances this way for reasons related to implicit prioritization, but the instances for Ordering are a mess and the question of why they use the A => Comparable[A] approach probably isn't worth thinking too hard about.

Related

Implement trait methods using subclasses' types

I want a trait Foo to provide transform method that would apply a function to it. Also, I want to force implementing classes to have an increment method that would somehow transform the object as well. Naive solution:
trait Foo {
def transform(fun: Foo => Foo): Foo = fun(this)
def increment(n: Int): Foo
}
case class A(a: Int) extends Foo {
// expecting available: transform(fun: A => A): A
// to be implemented: increment(n: Int): A
...
}
Above won't work... Inherited transform still expects Foo => Foo, not A => A and increment still wants to return Foo, not A.
One more attempt:
trait Foo {
def transform[C <: Foo](fun: C => C): C = fun(this.asInstanceOf[C])
def increment[C <: Foo](n: Int): C
}
case class A(a: Int) extends Foo {
def increment(n: Int) = A(a + n)
}
A will not compile - it will still complain about the signature.
Taking out the increment function, transform works. However asInstanceOf looks a bit unsafe. Also, I need to explicitly provide type parameter to transform:
val a = A(1)
a.transform[A](x => x.copy(x.a + 1)) // returns A(2)
I wonder if there's a smart way to have it done.
The most direct way of getting what you want is to move the type parameter up to the trait declaration. That gives trait Foo[C]{...}. However, using copy in your transform still won't work, since the Foo trait doesn't know anything about anything that extends it. You can give it a bit more information with self typing:
trait Foo[C] {
this: C =>
def transform(fun: C => C): C = fun(this)
def increment(n: Int): C
}
case class A(a: Int) extends Foo[A] {
def increment(n: Int) = A(a + n)
}
The A extends Foo[A] is a little awkward to use here, but it works, since now when you extend Foo, it provides that type information back to the trait. That's still a little bit awkward though. It turns out there's a technique called type classes that we can use here to potentially improve things. First, you set up your trait. In a type class, there is exactly one implementation of the trait per type, so each method should also take in the instance that you want to operate on:
trait Foo[C] {
def transform(c: C)(f: C => C): C
def increment(c: C, inc: Int): C
}
Next, in the companion object you set up instances of the typeclass for the types you care about:
case class A(a: Int)
object Foo {
implicit val ATransform = new Foo[A] {
def transform (base: A)(f: A => A) = f(base)
def increment(base: A, inc: Int) = A(base.a+inc)
}
//Convenience function for finding the instance for a type.
//With this, Foo[A] is equivalent to implicitly[Foo[A]]
def apply[C](implicit foo: Foo[C]) = foo
}
Now we can use the type class as follows:
val b = A(3)
Foo[A].transform(b)(x=>x.copy(a=x.a+1)) //A(4)
Foo[A].increment(b,5) //A(8)

What's wrong with delegation-based typeclasses encoding

Typeclasses coherence is a well-known problem.
For example a Monad has to be a Functor and a Traversable has to be a Functor as well. If has to be is represented via inheritance (Monad[F[_]] extends Functor[F[_]]) then there will most probably be ambiguity in implicit resolution.
I applied the rule of thumb: if you have a problem with inheritance replace it by delegation. Here is an example:
trait Semigroup[A] {
def append(a: A, b: A): A
}
trait Monoid[A] {
def zero(): A
val semigroup: Semigroup[A]
def append(a: A, b: A): A = semigroup.append(a, b)
}
implicit object IntSemigroup extends Semigroup[Int] {
override def append(a: Int, b: Int): Int = a + b
}
implicit object IntMonoid extends Monoid[Int] {
override def zero(): Int = 0
override val semigroup: Semigroup[Int] = IntSemigroup
}
def main(args: Array[String]): Unit = {
println(implicitly[Monoid[Int]].append(2, 3))
}
I guess this approach doesn't work since it's obvious but not used in scalaz/cats. Could you please point me to the problems?
With representing it using inheritance, you get inference for free - a Monad is automatically a Functor. With representing it using delegation, you don't.
You would have to define lots of implicit conversions to get around that, which would be a pain. But (simple) implicit conversions don't chain automatically in Scala, so with them, it still wouldn't infer Functor from Monad via the intermediate type class Applicative.
P.S. In practice, you usually don't get ambiguity in resolution if you do things right. That means, (a) use foo.some instead of Some(foo) and the like, and (b) use value classes or similar to semantically disambiguate types for which you wish to use different instances. And if all else fails, explicitly pass in the instance (which you can't do in Haskell).

How to construct an empty Iterable subclass, generically, and in Scala.js

Normally breakout would aid in conversion from one collection to another, but it doesn't seem to be able to infer the necessary colleciton constuctor for C:
import scala.collection.breakOut
object Utils {
implicit class IterableExtra[T, C[X] <: Iterable[X]](val list: C[T]) extends AnyVal {
def empty: C[T] = Iterable.empty[T].map(x => x)(breakOut)
}
}
Ideally this would work with minimal reflection, so that it might work in scala.js
Update I was also trying to use this in a different way, and I forgot to have the implicit at the outermost level:
def testIterableEmpty[B, I[X] <: Iterable[X]](implicit cbf: CanBuildFrom[I[B], B, I[B]]): I[B] = {
def emptyIter: I[B] = cbf().result()
emptyIter
}
scala> val x: List[Int] = testIterableEmpty[Int, List]
x: List[Int] = List()
breakOut is defined like so:
def breakOut[From, T, To](implicit b: CanBuildFrom[Nothing, T, To]): CanBuildFrom[From, T, To]
So it cannot be used to avoid passing a CanBuildFrom into your empty method - it requires one itself. Luckily, it is easy to write - you want to create a C[T] out of C[T], and the element type is T, so:
def empty(implicit cbf: CanBuildFrom[C[T], T, C[T]]): C[T] =
Iterable.empty[T].map(x => x)(breakOut)
Tho since you have a CanBuildFrom instance anyway, the implementation using it directly is straightforward too:
def empty(implicit cbf: CanBuildFrom[C[T], T, C[T]]): C[T] =
cbf().result()

Higher order type classes in scala

I am trying to understand typeclasses and so far i got to Monoids, which are simple enough:
object AbstractAlgebra {
case class Pair[A,B](a: A, b: B)
trait Monoid[T] {
def times(t1: T, t2: T): T
def unit: T
}
object Monoid {
implicit object MonoidIntPlus extends Monoid[Int] {
def times(i1: Int, i2: Int) = i1 + i2
def unit = 0
}
implicit object StringMonoid extends Monoid[String] {
def times(s1: String, s2: String) = s1 + s2
def unit = ""
}
implicit object PairOfMonoids extends Monoid[Pair[Monoid, Monoid]] = ???
}
}
I suppose my problem is the type Monoid[Pair[Monoid, Monoid]], cause I'm not really dealing with two monoid instances, only two classes that are implicit monoids, but I am not sure how to express that.
Any help or references would be appreciated
Monoid is not a type in itself. It's a type constructor, so Pair[Monoid, Monoid] makes no sense.
What you really want is actually the following: assuming that you have a Monoid type class instance for two given types A and B, then make an instance also for Pair[A, B].
This can be written as follows (the implementation is the most natural one you can derive):
implicit def monoidPair[A, B](implicit A: Monoid[A], B: Monoid[B]): Monoid[Pair[A, B]] = new Monoid[Pair[A, B]] {
def times(p1: Pair[A, B], p2: Pair[A, B]) =
Pair(A.times(p1.a, p2.a), B.times(p1.b, p2.b))
def unit = Pair(A.unit, B.unit)
}
This will do exactly what I explained before: If implicit instances for types Monoid[A] and Monoid[B] are found, then it puts a new implicit instance of type Monoid[Pair[A, B]] in scope.
Note. Your case class Pair[A, B] is already defined in Predef (although it's been deprecated since 2.11.0) as Tuple2[A, B] or (A, B).
Other note. If you don't like defining implicit instances as def or val, you can do the same with an implicit class:
implicit class MonoidPair[A, B](implicit A: Monoid[A], B: Monoid[B]) extends Monoid[Pair[A, B]] {
... //same body as before
}

Implement generics in trait and method

I have posted this question in scala-user forum,
https://groups.google.com/forum/#!topic/scala-user/xlr7KmlWdWI
and I received an answer which I am happy with. However, at the same time I want to make sure if that is the only conclusion. Thanks
My question is, say, I have,
trait Combinable[A] {
def join[B](l: List[A]): B
}
When I implement this trait with A as String and B as Int, for example,
class CombineString extends Combinable[String] {
override def join[Int](strings: List[String]) = string.size
}
Obviously, Int, next to join method, is not the Scala integer class and
compiling this code will fail. Alternatively, I could rewrite my trait as
trait Combinable[A, B] {
def join(l: List[A]): B
}
or
trait Combinable[A] {
def join[B](l: List[A])(f: List[A] => B): B
}
My question is, how can I implement the trait as defined in the first example as it is? If the first example has no practical use because of the way it is defined, why does the compiler not complaints? Thanks again.
You can not expect for compiler to understand what type combinations make sense for you, but you can specify this sense as relation between types in term of multiparameter implicits.
Result is basically combination of two of your rejected approaches, but with desired syntax.
First of two rejected forms became implicit type:
trait Combine[A, B] {
def apply(l: List[A]): B
}
Next you can define appropriate type combinations and their meaning
implicit object CombineStrings extends Combine[String, String] {
def apply(l: List[String]) = l.mkString
}
implicit object CombineInts extends Combine[Int, Int] {
def apply(l: List[Int]) = l.sum
}
implicit object CombinableIntAsString extends Combine[Int, String] {
def apply(l: List[Int]) = l.mkString(",")
}
Finally we modify second rejected form that hides f argument for implicit resulution:
trait Combinable[A] {
def join[B](l: List[A])(implicit combine: Combine[A, B]): B = combine(l)
}
Now you can define
val a = new Combinable[String] {}
val b = new Combinable[Int] {}
And check that
a.join[String](List("a", "b", "c"))
b.join[Int](List(1, 2, 3))
b.join[String](List(1, 2, 3))
runs nice while
a.join[Int](List("a", "b", "c"))
makes compiler cry until you could provide evidence of practical use of relation between String and Int in form of implicit value
My question is, how can I implement the trait as defined in the first example as it is?
class CombineString extends Combinable[String] {
override def join[B](strings: List[String]) = null.asInstanceOf[B]
// or, for that matter, anything and then .asInstanceOf[B]
}
How could the compiler know that's not what you want?