New Instances of Decorated Instances - scala

I have a set of decorator-traits (for simplicity here only trait T) mixing in classes (here subclasses of A).
trait T { def i: Int }
abstract class A
type AT = A with T
class B extends A
// class C extends A
// class D extends A
// ...
Now I have an instance a of e.g. class B which I handle as an instance of type AT (together with other A-subclass-AT-instances in a Seq[AT]).
val a: AT = new B with T { val i = 8 }
How can I generically decorate like this:
def toAT(a: A, i: Int): AT = {
// how to ???
}
An obvious solution I thought about is:
trait T { def i: Int }
abstract class A {
def asAT(i: Int): AT
}
class B extends A {
def asAT(ii: Int): AT = new B with T { val i = ii }
}
type AT = A with T
def toAT(a: A, i: Int): AT = a.asAT(i)
But I don´t want to pollute my classes B, C, ..., Z with a new method and there are other decorations, so for every decoration-combo I need a new method for all subclasses!
Is there a more generic way?
EDIT:
An example why I need the toAT method, but still with the obvious solution approach from above in terms of a redecorated method:
trait T { def b: Boolean}
type AT = A with T
abstract class A(val i: Int) {
def changedBy(x: Int): A
def redecorated(oldAT: AT): AT
}
class B(x: Int) extends A(x) {
def changedBy(x: Int): A = new B(i * x)
def redecorated(oldAT: AT): AT = new B(i) with T { val b = oldAT.b }
}
class C(x: Int) extends A(x) {
def changedBy(x: Int): A = new C(i * x * x)
def redecorated(oldAT: AT): AT = new C(i) with T { val b = oldAT.b }
}
val b = new B(1) with T { val b = true }
val c = new C(1) with T { val b = false }
val x = 8
val res: Seq[AT] = Seq(b,c) map { at => at.changedBy(x).redecorated(at) }

Basically, you can't do it.
One alternative is to use the auto proxy plugin, by Kevin Wright. See also here and here for more information about it.

Related

why scala compiler says type arguments does not conform to bounds?

I created Combiner trait with subclasses Complex and IntCombiner and my objective is to make Matrix work with both Complex and Int. But some reason it dosen't compile saying that
[com.implicits.TestImplicits1.IntCombiner] do not conform to class Matrix's type parameter bounds [T <: com.implicits.TestImplicits1.Combiner[T]]
val m1 = new Matrix[IntCombiner](3, 3)((1 to 9).sliding(3).map {
But as my understanding goes as IntContainer is the subclass of Combiner it should work. Why such an error please explain ?
object TestImplicits1 {
trait Combiner[T] {
def +(b: T): T
def *(b: T): T
}
class Complex(r: Double, i: Double) extends Combiner[Complex] {
val real = r
val im = i
override def +(b: Complex): Complex = {
new Complex(real + b.real, im + b.im)
}
override def *(b: Complex): Complex = {
new Complex((real * b.real) - (im * b.im), real * b.im + b.real * im)
}
}
class IntCombiner(a: Int) extends Combiner[Int] {
val v = a
override def *(b: Int): Int = v * b
override def +(b: Int): Int = v + b
}
class Matrix[T <: Combiner[T]](x1: Int, y1: Int)(ma: Seq[Seq[T]]) {
self =>
val x: Int = x1
val y: Int = y1
def dot(v1: Seq[T], v2: Seq[T]): T = {
v1.zip(v2).map { t: (T, T) => {
t._1 * t._2
}
}.reduce(_ + _)
}
}
object MatrixInt extends App {
def apply[T <: Combiner[T]](x1: Int, y1: Int)(s: Seq[Seq[T]]) = {
new Matrix[T](x1, y1)(s)
}
val m1 = new Matrix[IntCombiner](3, 3)((1 to 9).sliding(3).map {
x => x map { y => new IntCombiner(y) }
}.toSeq)
}
}
F-bounded polymorphism cannot be added to an existing Int class, because Int is just what it is, it does not know anything about your Combiner traits, so it cannot extend Combiner[Int]. You could wrap every Int into something like an IntWrapper <: Combiner[IntWrapper], but this would waste quite a bit of memory, and library design around F-bounded polymorphism tends to be tricky.
Here is a proposal based on ad-hoc polymorphism and typeclasses instead:
object TestImplicits1 {
trait Combiner[T] {
def +(a: T, b: T): T
def *(a: T, b: T): T
}
object syntax {
object combiner {
implicit class CombinerOps[A](a: A) {
def +(b: A)(implicit comb: Combiner[A]) = comb.+(a, b)
def *(b: A)(implicit comb: Combiner[A]) = comb.*(a, b)
}
}
}
case class Complex(re: Double, im: Double)
implicit val complexCombiner: Combiner[Complex] = new Combiner[Complex] {
override def +(a: Complex, b: Complex): Complex = {
Complex(a.re + b.re, a.im + b.im)
}
override def *(a: Complex, b: Complex): Complex = {
Complex((a.re * b.re) - (a.im * b.im), a.re * b.im + b.re * a.im)
}
}
implicit val intCombiner: Combiner[Int] = new Combiner[Int] {
override def *(a: Int, b: Int): Int = a * b
override def +(a: Int, b: Int): Int = a + b
}
class Matrix[T: Combiner](entries: Vector[Vector[T]]) {
def frobeniusNormSq: T = {
import syntax.combiner._
entries.map(_.map(x => x * x).reduce(_ + _)).reduce(_ + _)
}
}
}
I don't know what you attempted with dot there, your x1, x2 and ma seemed to be completely unused, so I added a simple square-of-Frobenius-norm example instead, just to show how the typeclasses and the syntactic sugar for operators work together. Please don't expect anything remotely resembling "high performance" from it - JVM traditionally never cared about rectangular arrays and number crunching (at least not on a single compute node; Spark & Co is a different story). At least your code won't be automatically transpiled to optimized CUDA code, that's for sure.

Scala design pattern - sealed trait with two generics, children method having same type object in arguments list

sorry if the title is not very explicative, but I don't know how to explain it. I'm a scala newbie and I'm struggling in finding a solution to my problem. Here's the snippet:
sealed trait Base[T, M] {
var value: Option[T] = None
def initialize(v: T): this.type = {
value = Some(v)
this
}
def combine[K <: M](other: K): M
}
class Child1 extends Base[String, Child1] {
override def combine[K <: Child1](other: K) = {
val c = new Child1()
c.initialize(value.get + " - " + other.value.get)
c
}
}
class Child2 extends Base[Long, Child2] {
override def combine[K <: Child2](other: K) = {
val c = new Child2()
c.initialize(value.get + other.value.get)
c
}
}
object Main extends App {
val c1a = new Child1()
c1a.initialize("a")
val c1b = new Child1()
c1b.initialize("b")
val c21 = new Child2()
c21.initialize(1)
val c22 = new Child2()
c22.initialize(2)
val m1 = Map("child1" -> c1a, "child2" -> c21)
val m2 = Map("child1" -> c1b, "child2" -> c22)
m1("child1").combine(m2("child1"))
}
What I want to achieve is that each subclass of Base can be combined only with objects of the same type.
The compiler complains when calling the combine method due to a mismatch in the type of the argument. Is this a correct approach? Or the structure of the classes for my purpose is to be rewritten?
EDIT
This should be ok as well:
sealed trait Base[T, M] {
var value: Option[T] = None
def initialize(v: T): this.type = {
value = Some(v)
this
}
def combine(other: M): M
}
class Child1 extends Base[String, Child1] {
override def combine(other: Child1) = {
val c = new Child1()
c.initialize(value.get + " - " + other.value.get)
c
}
}
class Child2 extends Base[Long, Child2] {
override def combine(other: Child2) = {
val c = new Child2()
c.initialize(value.get + other.value.get)
c
}
}
CURRENT SOLUTION
The solution I found so far:
val combined = (m1("child1"), m2("child1")) match {
case (a: Child1, b: Child1) => a.combine(b)
case _ => throw new Error("Error")
}
What I want to achieve is that each subclass of Base can be combined
only with objects of the same type.
Instead of using pattern match on (m1("child1"), m2("child1")) you can directly use type check on combine method on each child class. In addition, your code seem more imperative style, such as using var, I have refractored your code in more functional way.
sealed trait Base[T] {
val value: Option[T] = None
def combine[Other](other: Base[Other]): Base[T]
}
case class Child1(override val value: Option[String]) extends Base[String] {
override def combine[Other](other: Base[Other]) = {
other match {
case v: Child1 => this.copy(v.value)
case _ => throw new Error("Error")
}
}
}
case class Child2(override val value: Option[String]) extends Base[String] {
override def combine[Other](other: Base[Other]) = {
other match {
case v: Child2 => this.copy(v.value)
case _ => throw new Error("Error")
}
}
}
val child1 = Child1(Some("child1"))
val child2 = Child2(Some("child2"))
child1.combine(child2) //Will fail
val anotherChild1 = Child1(Some("Another child1"))
child1.combine(anotherChild1) //Will succeed.

Applying type classes until a fixpoint is reached in Scala

tl;dr: Is there a way to automatically apply a type class recursively until no changes are performed anymore?
I have defined case classes that represent symbolic computations like this
trait SymbolicComputation
case class ConstZero() extends SymbolicComputation
case class Const[T](t: T) extends SymbolicComputation
case class Sum[S1, S2](s1: S1, s2: S2) extends SymbolicComputation
case class Product[F1, F2](f1: F1, f2: F2) extends SymbolicComputation
// ...
along with a type class to simplify trees of such computations
trait CanSimplify[-F] {
type R
def simplify(f: F): R
}
trait LowestPriorityCanSimplify {
// Cannot simplify any further
implicit def canSimplifyIdentity[F] = new CanSimplify[F] {
type R = F
def simplify(f: F) = f
}
}
trait LowPriorityCanSimplify extends LowestPriorityCanSimplify {
// Simplify summands
implicit def canSimplifySummands[F1, F2](
implicit canSimplifyFirst: CanSimplify[F1],
canSimplifySecond: CanSimplify[F2]
) = new CanSimplify[Sum[F1, F2]] {
type R = Sum[canSimplifyFirst.R, canSimplifySecond.R]
def simplify(f: Sum[F1, F2]) = {
Sum(
canSimplifyFirst.simplify(f.s1),
canSimplifySecond.simplify(f.s2)
)
}
}
}
trait HighPriorityCanSimplify extends LowPriorityCanSimplify {
// 0 + x = x
implicit def canSimplifyZeroPlusF[F](
implicit canSimplify: CanSimplify[F]
) =
new CanSimplify[Sum[ConstZero, F]] {
type R = canSimplify.R
def simplify(f: Sum[ConstZero, F]) = {
canSimplify.simplify(f.s2)
}
}
// 0 * x = 0
implicit def canSimplifyZeroTimesF[F] =
new CanSimplify[Product[ConstZero, F]] {
type R = ConstZero
def simplify(f: Product[ConstZero, F]) = {
ConstZero()
}
}
}
object CanSimplify extends HighPriorityCanSimplify {
implicit class RichSimplifiable[F](f: F) {
def simplify(implicit canSimplify: CanSimplify[F]) =
canSimplify.simplify(f)
}
}
Now when applying once, one iteration of simplification is performed correctly
import CanSimplify._
val s = Sum(ConstZero(), Sum(Product(ConstZero(), Const(2.0)), Const(1.0)))
// => s: Sum[ConstZero,Sum[Product[ConstZero,Const[Double]],Const[Double]]] = Sum(ConstZero(),Sum(Product(ConstZero(),Const(2.0)),Const(1.0)))
s.simplify
// => res0: Sum[ConstZero,Const[Double]] = Sum(ConstZero(),Const(1.0))
But actually, we need multiple (in this case 2) iterations to get to the simplest form
s.simplify.simplify
// => res1: Const[Double] = Const(1.0)
One idea that is not elegant but could work is to add a type-level integer (Nat) type parameter to CanSimplify and reduce that type parameter in every implicit application. Then one could start with a high number (the maximum number of simplifications that should be made) and stop only when the second parameter reaches _0.
Is there a nicer solution to this problem?

A method that should only accept instances of A or B or C in Scala

I would ensure that a method should only accept instances of A or B or C. And I don't want to modify the code of A, B and C.
case class A
case class B
case class C
def method(aOrbOrc: Any) = ???
// method("toto") should not compile
You can use Type Class.
case class A(s: String)
case class B(i: Int)
case class C(i1: Int, i2: Int)
// Type Class
trait ABC[T] {
def bar(t: T): String
}
// Instances
implicit object ABC_A extends ABC[A] {
override def bar(t: A): String = "A : s = " + t.s
}
implicit object ABC_B extends ABC[B] {
override def bar(t: B): String = "B : i = " + t.i
}
implicit object ABC_C extends ABC[C] {
override def bar(t: C): String = "C : i1 = " + t.i1 + ", i2 = " + t.i2
}
def method[T](abc: T)(implicit instance: ABC[T]) = println(instance.bar(abc))
method(A("AAAAA")) // => A : s = AAAAA
method(B(123)) // => B : i = 123
method(C(9, 5)) // => C : i1 = 9, i2 = 5
method(1) // compilation error
You could use Miles Sabin's idea for implementing union types (code below is taken from Rex Kerr's variant):
trait Contra[-A] {}
type Union[A,B,C] = {
type Check[Z] = Contra[Contra[Z]] <:< Contra[Contra[A] with Contra[B] with Contra[C]]
}
then do:
def method[T: Union[A,B,C]#Check](t: T) = ???
for example:
def method[T: Union[Int,String,Boolean]#Check](t:T) = ???
method(1) // OK
method("foo") // OK
method(true) // OK
method(1.5) // does not compile
Read more about it here. And here is a link to Miles' post.

scala's spire framework : I am unable to operate on a group

I try to use spire, a math framework, but I have an error message:
import spire.algebra._
import spire.implicits._
trait AbGroup[A] extends Group[A]
final class Rationnel_Quadratique(val n1: Int = 2)(val coef: (Int, Int)) {
override def toString = {
coef match {
case (c, i) =>
s"$c + $i√$n"
}
}
def a() = coef._1
def b() = coef._2
def n() = n1
}
object Rationnel_Quadratique {
def apply(coef: (Int, Int),n: Int = 2)= {
new Rationnel_Quadratique(n)(coef)
}
}
object AbGroup {
implicit object RQAbGroup extends AbGroup[Rationnel_Quadratique] {
def +(a: Rationnel_Quadratique, b: Rationnel_Quadratique): Rationnel_Quadratique = Rationnel_Quadratique(coef=(a.a() + b.a(), a.b() + b.b()))
def inverse(a: Rationnel_Quadratique): Rationnel_Quadratique = Rationnel_Quadratique((-a.a(), -a.b()))
def id: Rationnel_Quadratique = Rationnel_Quadratique((0, 0))
}
}
object euler66_2 extends App {
val c = Rationnel_Quadratique((1, 2))
val d = Rationnel_Quadratique((3, 4))
val e = c + d
println(e)
}
the program is expected to add 1+2√2 and 3+4√2, but instead I have this error:
could not find implicit value for evidence parameter of type spire.algebra.AdditiveSemigroup[Rationnel_Quadratique]
val e = c + d
^
I think there is something essential I have missed (usage of implicits?)
It looks like you are not using Spire correctly.
Spire already has an AbGroup type, so you should be using that instead of redefining your own. Here's an example using a simple type I created called X.
import spire.implicits._
import spire.algebra._
case class X(n: BigInt)
object X {
implicit object XAbGroup extends AbGroup[X] {
def id: X = X(BigInt(0))
def op(lhs: X, rhs: X): X = X(lhs.n + rhs.n)
def inverse(lhs: X): X = X(-lhs.n)
}
}
def test(a: X, b: X): X = a |+| b
Note that with groups (as well as semigroups and monoids) you'd use |+| rather than +. To get plus, you'll want to define something with an AdditiveSemigroup (e.g. Semiring, or Ring, or Field or something).
You'll also use .inverse and |-| instead of unary and binary - if that makes sense.
Looking at your code, I am also not sure your actual number type is right. What will happen if I want to add two numbers with different values for n?
Anyway, hope this clears things up for you a bit.
EDIT: Since it seems like you're also getting hung up on Scala syntax, let me try to sketch a few designs that might work. First, there's always a more general solution:
import spire.implicits._
import spire.algebra._
import spire.math._
case class RQ(m: Map[Natural, SafeLong]) {
override def toString: String = m.map {
case (k, v) => if (k == 1) s"$v" else s"$v√$k" }.mkString(" + ")
}
object RQ {
implicit def abgroup[R <: Radical](implicit r: R): AbGroup[RQ] =
new AbGroup[RQ] {
def id: RQ = RQ(Map.empty)
def op(lhs: RQ, rhs: RQ): RQ = RQ(lhs.m + rhs.m)
def inverse(lhs: RQ): RQ = RQ(-lhs.m)
}
}
object Test {
def main(args: Array[String]) {
implicit val radical = _2
val x = RQ(Map(Natural(1) -> 1, Natural(2) -> 2))
val y = RQ(Map(Natural(1) -> 3, Natural(2) -> 4))
println(x)
println(y)
println(x |+| y)
}
}
This allows you to add different roots together without problem, at the cost of some indirection. You could also stick more closely to your design with something like this:
import spire.implicits._
import spire.algebra._
abstract class Radical(val n: Int) { override def toString: String = n.toString }
case object _2 extends Radical(2)
case object _3 extends Radical(3)
case class RQ[R <: Radical](a: Int, b: Int)(implicit r: R) {
override def toString: String = s"$a + $b√$r"
}
object RQ {
implicit def abgroup[R <: Radical](implicit r: R): AbGroup[RQ[R]] =
new AbGroup[RQ[R]] {
def id: RQ[R] = RQ[R](0, 0)
def op(lhs: RQ[R], rhs: RQ[R]): RQ[R] = RQ[R](lhs.a + rhs.a, lhs.b + rhs.b)
def inverse(lhs: RQ[R]): RQ[R] = RQ[R](-lhs.a, -lhs.b)
}
}
object Test {
def main(args: Array[String]) {
implicit val radical = _2
val x = RQ[_2.type](1, 2)
val y = RQ[_2.type](3, 4)
println(x)
println(y)
println(x |+| y)
}
}
This approach creates a fake type to represent whatever radical you are using (e.g. √2) and parameterizes QR on that type. This way you can be sure that no one will try to do additions that are invalid.
Hopefully one of these approaches will work for you.