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.
Related
I was playing with cats' Monoids in scala when I see that the monoid operations are extended for Tuples in a natural way:
import cats.Monoid
object mon {
implicit object IntMonoid extends Monoid[Int] {
def combine(a: Int, b: Int) = a*a + b*b
def empty = 0
}
implicit object ListMonoid extends Monoid[List[Int]] {
def combine(a: List[Int], b: List[Int]): List[Int] =
a.zip(b).map(z => z._1 * z._2)
def empty = List(1)
}
def comb[T](a: T, b: T)(implicit m: Monoid[T]) =
m.combine(a, b)
}
val list1 = List(1, 2, 3)
val list2 = List(2, 3, 4)
println(mon.comb(list1, list2)) // outputs: List(2, 6, 12) as expected
val int1 = 2
val int2 = 4
println(mon.comb(int1, int2)) // outputs: 20 as expected
val x = (list1, int1)
val y = (list2, int2)
println(mon.comb(x, y)) // outputs: (List(2, 6, 12),20)
The last output is expected in a 'natural' way, but how does de compiler knows how to do it?
I've been trying to look for it in Cats' source code, but I'm not as experienced in Scala as to be able to know what to look for. I suppose the same methods holds for similar constructions like semigroups.
Your question boils down to how implicit derivation of typeclasses for generic types work; so let's see two examples:
A case where we want to provide an instance no matter what the generic is:
// Similar to the code you had, but without being tied to just List[Int],
// Since in this case the Int part is irrelevant.
implicit def monoidList[A]: Monoid[List[A]] =
new Monoid[List[A]] {
override final val empty: List[A] = Nil
override final def combine(l1: List[A], l2: List[A]): List[A] =
l1 ::: l2
}
A case where we require a proof of the generic type to provide the instance of the complex type:
implicit def optionMonoid[A](implicit aMonoid: Monoid[A]): Monoid[Option[A]] =
new Monoid[Option[A]] {
override final val empty: Option[A] = None
override final def combine(o1: Option[A], o2: Option[A]): Option[A] =
(o1, o2) match {
case (None, None) => None
case (Some(a), None) => Some(a)
case (None, Some(a)) => Some(a)
case (Some(a1), Some(a1)) => Some(aMonoid.combine(a1, a2))
}
}
Thus, you can now imagine how the Monoid[Tuple2[A, B]] of cats works, but just for completeness the code would be like this:
implicit def tuple2Monoid[A, B](implicit aMonoid: Monoid[A], bMonoid: Monoid[B]): Monoid[(A, B)] =
new Monoid[(A, B)] {
override final def empty: (A, B) =
(aMonoid.empty, bMonoid.empty)
override final def combine(t1: (A, B), t2: (A, B)): (A, B) =
(t1, t2) match {
case ((a1, b1), (a2, b2)) => (aMonoid.combine(a1, a2), bMonoid.combine(b1, b2))
}
}
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
Just started learning Scalaz. Here is my code
trait Monoid[A] {
def mappend(a1: A, a2: A): A
def mzero: A
}
object Monoid {
implicit val IntMonoid: Monoid[Int] = new Monoid[Int] {
def mappend(a1: Int, a2: Int): Int = a1 + a2
def mzero: Int = 0
}
implicit val StringMonoid: Monoid[String] = new Monoid[String] {
def mappend(a1: String, a2: String): String = a1 + a2
def mzero: String = ""
}
}
trait MonoidOp[A] {
val F: Monoid[A]
val value: A
def |+|(a2: A): A = F.mappend(value, a2)
}
object MonoidOp{
implicit def toMonoidOp[A: Monoid](a: A): MonoidOp[A] = new MonoidOp[A]{
val F = implicitly[Monoid[A]]
val value = a
}
}
I have defined a function (just for the sake of it)
def addXY[A: Monoid](x: A, y: A): A = x |+| y
I want to lift it so that it could be used using Containers like Option, List, etc. But when I do this
def addXYOptioned = Functor[Option].lift(addXY)
It says error: could not find implicit value for evidence parameter of type scalaz.Monoid[A]
def addOptioned = Functor[Option].lift(addXY)
How to lift such functions?
Your method addXY needs a Monoid[A] but there is no Monoid[A] in scope when used in addXYOptioned, so you also need to add the Monoid constraint to addXYOptioned.
The next problem is that Functor.lift only lifts a function A => B, but we can use Apply.lift2 to lift a function (A, B) => C.
Using the Monoid from Scalaz itself :
import scalaz._, Scalaz._
def addXY[A: Monoid](x: A, y: A): A = x |+| y
def addXYOptioned[A: Monoid] = Apply[Option].lift2(addXY[A] _)
We could generalize addXYOptioned to make it possible to lift addXY into any type constructor with an Apply instance :
def addXYApply[F[_]: Apply, A: Monoid] = Apply[F].lift2(addXY[A] _)
addXYApply[List, Int].apply(List(1,2), List(3,4))
// List[Int] = List(4, 5, 5, 6)
addXYApply[Option, Int].apply(1.some, 2.some)
// Option[Int] = Some(3)
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.
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)