Problems with contravariance in Scala - scala

I want to define a type-class like this:
trait CanFold[-T, R] {
def sum(acc: R, elem: T): R
def zero: R
}
implicit object CanFoldInts extends CanFold[Int, Int] {
def sum(x: Int, y: Int) = x + y
def zero = 0
}
implicit object CanFoldSeqs extends CanFold[Traversable[_], Traversable[_]] {
def sum(x: Traversable[_], y: Traversable[_]) = x ++ y
def zero = Traversable()
}
def sum[A, B](list: Traversable[A])(implicit adder: CanFold[A, B]): B =
list.foldLeft(adder.zero)((acc,e) => adder.sum(acc, e))
However, the problem is when I do this I get a Traversable[Any] and it
would be nice to get a Traversable[Int] instead:
scala> sum(List(1,2,3) :: List(4, 5) :: Nil)
res10: Traversable[Any] = List(1, 2, 3, 4, 5)
To make matters worse, I cannot define an implicit for
Traversable[Int] after defining one for Traversable[_], because then
the definitions would cause ambiguity. After pulling my hair out I
gave up.
Is there any way I could make that sum return a
Traversable[T] instead of a Traversable[Any]?
Looking at how sum() is defined on Seq in Scala's library, I can see it works with Numeric, which is invariant, but I want default implementations for supertypes and having the result be different than the input (same as the fold operation) is nice.

The only way I know to add type parameters to such type classes is to use a def instead of an object:
implicit def CanFoldSeqs[A] = new CanFold[Traversable[A], Traversable[A]] {
def sum(x: Traversable[A], y: Traversable[A]) = x ++ y
def zero = Traversable()
}
scala> sum(List(1, 2, 3) :: List(4, 5) :: Nil)
res0: Traversable[Int] = List(1, 2, 3, 4, 5)

Related

How to create function which would make flat List from arbitrarily deeply nested lists?

Is it possible to write function in scala which would take list of arbitrarily deeply nested lists and transform it recursively into flat list? For example:
flatten(List(List(1), List(List(2), 3), 4))
should return
List(1,2,3,4)
I did some tries with shapeless but without effect:
object flatten extends (List ~> List) {
def apply[T](s: List[T]) = s.map {
case l: List[T] => apply(s)
case x => x
}
}
This gives me:
type mismatch
found: List[Any]
required: List[T]
Would be also great if it can deduct right type (in case of example List[Int] and not List[Any])
The thing is, you don't receive a List[T] in input, but a List[Any] where Any is a mix of T and List[Any].
So if you know the type of leaf elements, you could potentially use a type parameter T to represent it and flatmap elements by recursively pattern matching on either T or List[Any]:
import scala.reflect.ClassTag
def flatten[T: ClassTag](list: List[Any]): List[T] =
list.flatMap {
case x: T => List(x)
case sub: List[Any] => flatten[T](sub)
}
flatten[Int](List(List(1), List(List(2), 3), 4))
// List[Int] = List(1, 2, 3, 4)
Your desired flatten is intrinsically untyped. You are putting elements (let's say they have type E), lists thereof (List[E]), lists thereof (List[List[E]]), etc. into one list, which must have type List[Any], because its elements don't have anything in common. Shapeless is all about having descriptive types and transforming between them, so it has nothing for you. Furthermore, look at your function's definition:
def apply[T](s: List[T]) = s.flatMap { // should be flatMap, conceptually
case l: List[T] => apply(l) // should be l, conceptually
case x => List(x) // should be singleton list, conceptually
}
So, s is a List[T], and s.map is giving you each of the Ts in turn. You then use a type-case, and, in one of the arms, you check whether l: T is actually a l: List[T]. That is, you check that List[T] <: T. This is weird, and signifies that your function is incorrect.
If you really want to use Shapeless, accurately describe your input with types. We want this interface for flatten[T]:
If it receives a t: T, then it returns List(t): List[T].
If it receives a l: List[X], where X is a valid input to flatten[T], it flattens each X, then outputs the concatenation of the results as one, big List[T].
If it receives a h: H where H <: HList, where each element of H is a valid input to flatten[T], each element is flattened and the results are concatenated into one List[T].
This is its implementation:
object flatten extends Poly1 {
implicit def caseT[T] = at[T](List(_))
implicit def caseList[T, X](implicit e: Case.Aux[X, List[T]])
= at[List[X]](_.flatMap(e))
implicit def caseHNil[T, N <: HNil] = at[N](_ => List[T]())
implicit def caseHCons[T, H, R <: HList](implicit hf: Case.Aux[H, List[T]],
rf: Case.Aux[R, List[T]])
= at[H :: R] { case h :: r => hf(h) ++ rf(r) }
final class Specialized[T] {
def apply[X](x: X)(implicit c: Case.Aux[X, List[T]]): List[T] = c(x)
}
def apply[T]: Specialized[T] = new Specialized
}
With usage:
scala> flatten[Int]((1 :: HNil) :: ((2 :: HNil) :: 3 :: HNil) :: 4 :: HNil)
List(1, 2, 3, 4)
scala> flatten[Int](1 :: List(2, 3) :: List(List(4, 5), List(), List(6, 7)) :: List(8 :: List(9, 10) :: HNil, 11 :: List(12, 13, 14) :: HNil) :: HNil)
List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
The alternative is to simply use the correct data structure. In this context, the correct structure is called the free monad on List, also known as the rose tree:
sealed trait Free[M[+_], +A] {
def flatten(implicit M: Monad[M]): M[A]
}
case class Pure[M[+_], +A](x: A) extends Free[M, A] {
override def flatten(implicit M: Monad[M]) = M.pure(x)
}
case class Step[M[+_], +A](step: M[Free[M, A]]) extends Free[M, A] {
override def flatten(implicit M: Monad[M]) = step.flatMap(_.flatten)
}
// for convenience
object Rose {
type Rose[+A] = Free[List, A]
type Leaf[+A] = Pure[List, A]
type Branch[+A] = Step[List, A]
object Leaf {
def apply[A](x: A): Leaf[A] = Pure(x)
def unapply[A](x: Leaf[A]): Some[A] = Some(x.x)
}
object Branch {
def apply[A](xs: Rose[A]*): Branch[A] = Step(xs.toList)
def unapplySeq[A](xs: Branch[A]): Some[List[Rose[A]]] = Some(xs.step)
}
}
// specialized:
// sealed trait Rose[+A] { def flatten: List[A] }
// case class Leaf[+A](x: A) extends Rose[A] { override def flatten = List(x) }
// case class Branch[+A](x: List[Rose[A]]) extends Rose[A] { override def flatten = x.flatMap(_.flatten) }
Usage:
scala> Branch(Branch(Leaf(1)), Branch(Branch(Leaf(2)), Leaf(3)), Leaf(4)).flatten

Recursive type for tuple like type

I'm trying to define a method ConcatToList would be able to convert some objects of type T~T or T~T~T or T~T~T~T or ...
to a List[T].
My problem comes with how I should go about defining the type of ConcatToList
def ConcatToList[T](concat: ~[T, ???]) = ...
what should I replace ??? by ?
I'll assume a representation like this:
class ~[I, L](val init: I, val last: L)
That you instantiate like this:
scala> val x: Int ~ Int ~ Int ~ Int = new ~(new ~(new ~(1, 2), 3), 4)
x: ~[~[~[Int,Int],Int],Int] = $tilde#3e6fa38a
You're not going to be able to write your ConcatToList method with a signature of the form you suggest, since there's no way to write a type constraint that describes exactly the types for which this operation is valid. Instead you can use a type class:
trait TildeToList[T] {
type Elem
def apply(t: T): List[Elem]
}
object TildeToList {
type Aux[T, E] = TildeToList[T] { type Elem = E }
implicit def baseTildeToList[E]: Aux[E ~ E, E] = new TildeToList[E ~ E] {
type Elem = E
def apply(t: E ~ E): List[E] = List(t.init, t.last)
}
implicit def recTildeToList[I, L](implicit ttl: Aux[I, L]): Aux[I ~ L, L] =
new TildeToList[I ~ L] {
type Elem = L
def apply(t: I ~ L): List[L] = ttl(t.init) :+ t.last
}
}
And then:
def tildeToList[T](t: T)(implicit ttl: TildeToList[T]): List[ttl.Elem] = ttl(t)
Which works like this:
scala> tildeToList(x)
res0: List[Int] = List(1, 2, 3, 4)
Note that what we get back is appropriately statically typed.
If you try to use it on a value that doesn't have an appropriate shape, you'll get a compile-time error:
scala> tildeToList(new ~('a, "a"))
<console>:16: error: could not find implicit value for parameter ttl: TildeToList[~[Symbol,String]]
tildeToList(new ~('a, "a"))
^
Which is presumably what you want.
The next code works for lists of mixed types:
case class ~~[T, G](l: T, r: G)
def concat[T, G](v: ~~[T, G]): List[T] = (v.l, v.r) match {
case (left, right : ~~[T, _]) => left :: concat(right)
case (left, right: T) => List(left, right)
}
println(concat(~~(2, 3))) // List(2, 3)
println(concat(~~(2, ~~(4, 5)))) // List(2, 4, 5)
println(concat(~~(2, ~~(4, ~~(5, 6))))) // List(2, 4, 5, 6)
println(concat(~~(2, ~~("s", 3.3)))) // List(2, s, 3.3)
// but
println(concat(~~(~~("s", 3.3), 2))) // List(~~(s, 3.3), 2)
P.S. I will leave this as an example of simple approach, but see Travis response for a better type-safer way

constructing empty value of type that implements Seq

I have a trait like the following
private class SeqConverter[T](implicit val conv : Converter[T]) extends Converter[Seq[T]] {
def toJs(x: Seq[T]): JsAny = {
x.foldLeft(JsArray[JsAny]()) { (acc, next) =>
acc.+:(conv.toJs(next))
}
}
def toScala(x: JsAny): Seq[T] = {
val arr = x.asInstanceOf[JsArray[JsObject]]
var lst = List[T]()
arr foreach { x =>
lst = conv.toScala(x) :: lst
}
lst
}
}
I want to have something more like this
private class SeqConverter[T, F <: Seq[T]](implicit val conv : Converter[T]) extends Converter[F] {
def toJs(x: F): JsAny = {
x.foldLeft(JsArray[JsAny]()) { (acc, next) =>
acc.+:(conv.toJs(next))
}
}
def toScala(x: JsAny): Seq[T] = {
//need to construct empty F here to build it
}
}
But the problem is I have no way to get a member of F in order to start preforming construction of it. Is there any way I could get this to exist? It seems like there should be some kind of way to construct an empty member of F so so that I could use +: in order to convert from 1 kind of sequence to another. Does anything like that exist?
UPDATE: if you want to avoid depending on Scalaz, you can define your own type class and instances thereof:
import scala.language.higherKinds
trait Coll[TS[_], T] {
def zero: TS[T]
def append(a: TS[T], b: TS[T]): TS[T]
def point(x: T): TS[T]
}
object Coll {
implicit def listOfTIsColl[T] = new Coll[List, T] {
def zero = Nil
def append(a: List[T], b: List[T]) = a ++ b
def point(x: T) = List(x)
}
implicit def vectorOfTIsColl[T] = new Coll[Vector, T] {
def zero = Vector.empty
def append(a: Vector[T], b: Vector[T]) = a ++ b
def point(x: T) = Vector(x)
}
}
def foo[T, U, TS[_]](xs: TS[T], x: U)(implicit
coll: Coll[TS, T],
ev1: TS[T] <:< Seq[T],
ev2: U =:= T
) = {
(coll.zero, coll.append(coll.zero, coll.point(x)))
}
assert(foo(Vector(1, 2, 3), 4) == (Vector(), Vector(4)))
// foo(Vector(1, 2, 3), 4.4) -- error: Cannot prove that Double =:= Int
// foo(Vector(1, 2, 3), "hello") -- error: Cannot prove that String =:= Int
Note that it's necessary for T and U to be separate type parameters; with def foo[T, TS[_]](xs: TS[T], x: T) ..., you'd be able to use foo as expected, but things like foo(Vector(1, 2, 3), "hello") would work and the type inferencer would infer a type like Vector[Any]. However, with the above, stricter definition of foo, this won't be allowed, which is, at least in idiomatic functional code, desirable.
Scalaz based solution:
Scalaz Monoid and Applicative will help you:
import scalaz._
import Scalaz._
scala> Monoid[List[Int]].zero
res0: List[Int] = List()
scala> Monoid[Vector[Int]].zero
res1: Vector[Int] = Vector()
scala> Monoid[Vector[Int]].append(Vector(1, 2), Vector(3, 4))
res2: Vector[Int] = Vector(1, 2, 3, 4)
and
scala> Applicative[Vector].point(1)
res0: Vector[Int] = Vector(1)
Then, combining Monoid and Applicative will give you all of zero, append, and point/pure:
def foo[T, TS[_], U](xs: TS[T], x: U)(implicit
monoid: Monoid[TS[T]],
applic: Applicative[TS],
ev1: TS[T] <:< Seq[T],
ev2: U =:= T
) = {
(monoid.zero,
monoid.append(monoid.zero, applic.point(x)))
}
then:
> foo(Vector(1, 2, 3), 4)
res1 = (Vector(),Vector(4))
I'm not confident there aren't any conciser solutions, e.g. one that relies on just one type class, but this one seems to work correctly.

"update" method with variable-length index in Scala

I was writing code for something like an array with variable dimensions. What I do is to maintain a linear underlying collections and wrap it up with index access methods. Since the dimension of the data structure is not known, I write something like
def apply(i: Int*): Double = ...
And it works perfectly. However, I cannot do the same thing to update method and operators like +=, so I end up writing methods like
def set(v: Double, i: Int*) ...
def add(v: Double, i: Int*) ...
which is fine but not what I really want. I guess the problem about update may be fixed in two ways:
Change the order of arguments in update function, which makes it look weird.
Allow variable-length arguments not as the last one. I find this questions asked in a general setting and it can be solved by using currying functions, which does not apply here.
The problem about += seems more complicated and it even exists when the index is of fixed length. Maybe we can add an object that has += operator and use this(...) to get the object (so that this(...) += v will invoke some method as we expect), but that will conflict with the apply method.
If anyone has solution to any of the above questions or has a reason why we shouldn't be able to write code like this, please share your ideas! Thanks~
update is a fairly peculiar artefact in Scala because it is mainly syntactic sugar and doesn't correspond to any particular method signature. This means that we can be creative and give update an arity-polymorphic signature,
scala> class Indexed { def update[P <: Product](p: P) = p }
defined class Indexed
scala> val i = new Indexed
i: Indexed = Indexed#1ea0e836
scala> i(0) = 1.0
res0: (Int, Double) = (0,1.0)
scala> i(0, 1) = 1.0
res1: (Int, Int, Double) = (0,1,1.0)
scala> i(0, 1, 2) = 1.0
res2: (Int, Int, Int, Double) = (0,1,2,1.0)
scala> i(0, 1, 2, 3) = 1.0
res3: (Int, Int, Int, Int, Double) = (0,1,2,3,1.0)
As it stands, this leaves the types of the indices on the LHS and the type of the value on the RHS completely unconstrained,
scala> i(23, true, 'c') = "foo"
res4: (Int, Boolean, Char, String) = (23,true,c,foo)
but we can fix that with some implicit evidence provided by the new support for tuples in shapeless 2.0.0-SNAPSHOT,
scala> import shapeless._
import shapeless._
scala> import syntax.tuple._
import syntax.tuple._
scala> class Indexed {
| def update[P <: Product, I](p: P)
| (implicit
| init: TupleInit.Aux[P, I],
| toList: TupleToList[I, Int],
| last: TupleLast.Aux[P, Double]) = (toList(init(p)), last(p))
| }
defined class Indexed
scala> val i = new Indexed
i: Indexed = Indexed#76ab909a
scala> i(0) = 1.0
res10: (List[Int], Double) = (List(0),1.0)
scala> i(0, 1) = 2.0
res11: (List[Int], Double) = (List(0, 1),2.0)
scala> i(0, 1, 2) = 3.0
res12: (List[Int], Double) = (List(0, 1, 2),3.0)
scala> i(0, 1, 2, 3) = 4.0
res13: (List[Int], Double) = (List(0, 1, 2, 3),4.0)
scala> i(0, 1, 2) = "foo" // Doesn't compile
<console>:22: error: could not find implicit value for parameter
last: shapeless.ops.tuple.TupleLast.Aux[(Int, Int, Int, String),Double]
i(0, 1, 2) = "foo" // Doesn't compile
^
scala> i(23, "foo", true) = 5.0 // Doesn't compile
<console>:22: error: could not find implicit value for parameter
toList: shapeless.ops.tuple.TupleToList[I,Int]
i(23, "foo", true) = 5.0 // Doesn't compile
^
The simplest solution I see right now is to have many different overloads of update for every dimension that you want to support. Say that you can determine that the maximum dimension that you'll ever use is 10, this means that you'll need 10 overloads. This might not seem very practical, but i can easily be abstracted away so it is very much practical actually:
trait MultiKeyUpdate[K, V] {
def doUpdate( k: K* )( v: V )
def update(k1: K, v: V) { doUpdate( k1 )( v ) }
def update(k1: K, k2: K, v: V) { doUpdate( k1, k2 )( v ) }
def update(k1: K, k2: K, k3: K, v: V) { doUpdate( k1, k2, k3 )( v ) }
// ... and so on, up until max dimension ...
}
Usage:
class C extends MultiKeyUpdate[Int, Double] {
def apply(i: Int*): Double = {
println("Returning element " + i.mkString("[",",","]"))
123
}
def doUpdate( i: Int* )( v: Double ) {
println("Updating element " + i.mkString("[",",","]") + " to value " + v)
}
}
And some test in the REPL:
scala> val o = new C
o: C = C#12798c1
scala> o(1,2,3)
Returning element [1,2,3]
res3: Double = 123.0
scala> o(1,2,3) = 5.0
Updating element [1,2,3] to value 5.0
scala> o(1,2,3) += 7.0
Returning element [1,2,3]
Updating element [1,2,3] to value 130.0
class SetMe {
def set(i: Int*)(v: Double) { println("Set "+v+" with "+i.mkString(",")) }
}
scala> (new SetMe).set(4,7,19,3)(math.Pi)
Set 3.141592653589793 with 4,7,19,3
Can't do that trick with update itself, however. Might be worth filing an enhancement request.

Scala - Co/Contra-Variance as applied to implicit parameter selection

I've got a trait like this:
trait CanFold[-T, R] {
def sum(acc: R, elem: T): R
def zero: R
}
With a function that works with it like this:
def sum[A, B](list: Traversable[A])(implicit adder: CanFold[A, B]): B =
list.foldLeft(adder.zero)((acc,e) => adder.sum(acc, e))
The intention is to do something like this:
implicit def CanFoldSeqs[A] = new CanFold[Traversable[A], Traversable[A]] {
def sum(x: Traversable[A], y: Traversable[A]) = x ++ y
def zero = Traversable()
}
sum(List(1, 2, 3) :: List(4, 5) :: Nil)
//=> Traversable[Int] = List(1, 2, 3, 4, 5)
So it's a type-class for types for which the environment already knows how to fold and can be defined for Ints, Strings, whatever.
My problem is that I want to also have more-specific implicits that take priority, like this:
implicit def CanFoldSets[A] = new CanFold[Set[A], Set[A]] {
def sum(x: Set[A], y: Set[A]) = x ++ y
def zero = Set.empty[A]
}
sum(Set(1,2) :: Set(3,4) :: Nil)
//=> Set[Int] = Set(1, 2, 3, 4)
However that method call generates a conflict, as there's ambiguity:
both method CanFoldSeqs in object ...
and method CanFoldSets in object ...
match expected type CanFold[Set[Int], B]
So what I want is for the compiler to search for the most specific implicit between Any and my type. The intent is to provide default implementations for base types that can be overridden easily for more specific sub-types, without shadowing which is ugly.
I'm may be wishfully thinking here, but one can only hope :-)
The usual approach in a situation like this takes advantage of the way that implicits are prioritized by inheritance:
trait LowPriorityCanFoldInstances {
implicit def CanFoldSeqs[A] = new CanFold[Traversable[A], Traversable[A]] {
def sum(x: Traversable[A], y: Traversable[A]) = x ++ y
def zero = Traversable()
}
}
object CanFoldInstances extends LowPriorityCanFoldInstances {
implicit def CanFoldSets[A] = new CanFold[Set[A], Set[A]] {
def sum(x: Set[A], y: Set[A]) = x ++ y
def zero = Set.empty[A]
}
}
import CanFoldInstances._
Now the Set instance will be used when it's applicable, but the one for Traversable is still available when it's not.