Besides OOP and overriding, here is another solution:
- Scaler, (T, Int) T, T Tree. Scaler , . -. , Node . , . :)
, :
import language.implicitConversions
sealed trait Tree
case class Node[L <: Tree, R <: Tree](l: L, r: R) extends Tree
case class Leaf(n: Int) extends Tree
trait Scaler[T <: Tree] extends ((T, Int) => T)
object Scaler {
implicit object scalesLeafs extends Scaler[Leaf] {
def apply(l: Leaf, s: Int) =
Leaf(l.n * s)
}
implicit def scalesNodes[L <: Tree: Scaler, R <: Tree: Scaler] = new Scaler[Node[L,R]] {
val ls = implicitly[Scaler[L]]
val rs = implicitly[Scaler[R]]
def apply(n: Node[L,R], s: Int) =
Node(ls(n.l, s), rs(n.r, s))
}
}
object demo extends App {
def scale[T <: Tree](t: T, s: Int)(implicit ev: Scaler[T]): T =
ev(t, s)
val check1 = scale(Leaf(3), 5)
val check2 = scale(Node(Leaf(3), Leaf(7)), 5)
Console println check1.n
Console println check2.l.n
Console println check2.r.n
}
. : , , , , , .