Lifting a function which takes implicit parameter using functor (Scalaz7) - scala

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)

Related

Tagless final example in Scala requires superfluous second interp arg

I'm playing around with implementing a tagless final DSL & interpreter in Scala, based on this blog post written in Haskell.
I can get an example running - see code below, but I don't quite understand why I need testVal(Interp)(Interp). If I only supply a single Interp argument, then I get the following compile errors:
Error:(29, 24) could not find implicit value for evidence parameter of type Test.Expr[Test.Id]
val x = testVal(Interp)
Error:(29, 24) not enough arguments for method testVal: (implicit evidence$1: Test.Expr[Test.Id])Test.Id[Int].
Unspecified value parameter evidence$1.
val x = testVal(Interp)
Is there a simple way to eliminate one of the Interp arguments?
object Test {
trait Expr[F[_]] {
def const(i: Int): F[Int]
def lam[A, B](f: F[A] => F[B]): F[A => B]
def app[A, B](f: F[A => B], a: F[A]): F[B]
def add(x: F[Int], y: F[Int]): F[Int]
}
type Id[A] = A
object Interp extends Expr[Id] {
override def const(i: Int): Id[Int] = i
override def lam[A, B](f: Id[A] => Id[B]): Id[A => B] = f
override def app[A, B](f: Id[A => B], a: Id[A]): Id[B] = f(a)
override def add(x: Id[Int], y: Id[Int]): Id[Int] = x + y
}
def testVal[F[_]: Expr](f: Expr[F]): F[Int] =
f.app(
f.lam[Int, Int](
x => f.add(x, f.const(1))),
f.const(10)
)
def main(args: Array[String]): Unit = {
// val x = testVal(Interp) -- won't compile
val x = testVal(Interp)(Interp)
println(x)
}
}
The syntax
def f[X: Y](args: Types): Res = { ... }
is a shortcut for
def f[X](args: Types)(implicit yx: Y[X]): Res = { ... }
so if you write
def testVal[F[_]: Expr](f: Expr[F]): F[Int] = { ... }
then it's the same as if you wrote
def testVal[F[_]](f: Expr[F])(implicit redundant: Expr[F]): F[Int] = { ... }
but you obviously don't need the same Expr[F] twice.
The signature should be either
def testVal[F[_]: Expr]: F[Int]
or
def testVal[F[_]](implicit f: Expr[F]): F[Int]
but not both at the same time.
Here is a full example, which also shows how to get the f using implicitly in the case that you decide to use the F: Expr variant (which does not assign a name to the implicit argument):
import scala.language.higherKinds
object Test {
trait Expr[F[_]] {
def const(i: Int): F[Int]
def lam[A, B](f: F[A] => F[B]): F[A => B]
def app[A, B](f: F[A => B], a: F[A]): F[B]
def add(x: F[Int], y: F[Int]): F[Int]
}
type Id[A] = A
object Interp extends Expr[Id] {
override def const(i: Int): Id[Int] = i
override def lam[A, B](f: Id[A] => Id[B]): Id[A => B] = f
override def app[A, B](f: Id[A => B], a: Id[A]): Id[B] = f(a)
override def add(x: Id[Int], y: Id[Int]): Id[Int] = x + y
}
def testVal[F[_]: Expr]: F[Int] = {
implicit val f = implicitly[Expr[F]]
f.app(
f.lam[Int, Int](
x => f.add(x, f.const(1))),
f.const(10)
)
}
def main(args: Array[String]): Unit = {
val x = testVal(Interp)
println(x)
}
}
Moreover, if you make Interp itself implicit, then you can omit all argument lists when invoking testVal, and instead write just
val x = testVal // no arguments at all.

Scala: abstracting over a path-dependent type in impilicit parameter

Let's say I have a class:
abstract class NumericCombine[A:Numeric,B:Numeric]{
type AB <: AnyVal
}
I want to define a function that returns a value of type NumericCombine[A,B].AB. for instance:
def plus[A: Numeric,B:Numeric](x: A, y: B): NumericCombine[A,B].AB
but the compiler doesn't let me reference .AB in plus.
FYI, this is the context of this question.
I want to provide:
implicit object IntFloat extends NumericCombine[Int,Float]{override type AB = Float}
implicit object FloatInt extends NumericCombine[Float,Int]{override type AB = Float}
and its other 44 friends (7*6-2) so that I can define my plus as below:
def plus[A: Numeric,B:Numeric](x: A, y: B): NumericCombine[A,B].AB =
{
type AB = Numeric[NumericCombine[A,B].AB]
implicitly[AB].plus(x.asInstanceOf[AB],y.asInstanceOf[AB])
}
plus(1f,2)//=3f
plus(1,2f)//=3f
I am aware of the fact that value conversions in Scala allows me to define
def plus[T](a: T, b: T)(implicit ev:Numeric[T]): T = ev.plus(a,b)
and achieve the behaviour above as suggested here, but since I want to use this function as part of a bigger function (which is described in the link mentioned as the context of this question), I need to parametrize the function with both A and B.
Update:
I made some good progress with this.
My NumericCombine now looks like this:
abstract class NumericCombine[A: Numeric, B: Numeric] {
type AB <: AnyVal
def fromA(x: A): AB
def fromB(y: B): AB
val numeric: Numeric[AB]
def plus(x: A, y: B): AB = numeric.plus(fromA(x), fromB(y))
def minus(x: A, y: B): AB = numeric.minus(fromA(x), fromB(y))
def times(x: A, y: B): AB = numeric.times(fromA(x), fromB(y))
}
and My plus function looks like:
def plus[A: Numeric, B: Numeric](x: A, y: B)(implicit ev:NumericCombine[A,B])
: ev.AB = ev.plus(x, y)
The weighted average function requiring plus ended up becoming a bit more complicated:
def accumulateWeightedValue[A: Numeric,B: Numeric]
(accum: (A, NumericCombine[A, B]#AB), ValueWithWeight: (A, B))
(implicit combine: NumericCombine[A, B], timesNumeric: Numeric[NumericCombine[A, B]#AB])
:(A,NumericCombine[A, B]#AB)=
this is a function that takes (A,AB),(A,B) and returns (A,AB). I use it internally inside weightedSum which just aggregates over this:
def weightedSum[A: Numeric,B: Numeric](weightedValues: GenTraversable[(A, B)])
(implicit numericCombine: NumericCombine[A, B], plusNumeric: Numeric[NumericCombine[A, B]#AB])
: (A, NumericCombine[A, B]#AB)
Now, this compiles fine. It does seem to have a problem with the second implicit parameter. ie Numeric[AB] when I run it with implicit values for say NumericCombine[Int,Float] present. It gives me:
could not find implicit value for parameter plusNumeric:
Numeric[NumericCombine[Int,Float]#AB]
note that in NumericCombine, I have a Numeric[AB] which should be available for implicit look-up. storing it locally, in the case of [Int,Float]:
val lst: Seq[(Int, Float)] =List((1,3f),(1,4f))
implicit val num: Numeric[Float] = IntFloat.numeric //IntFloat extends NumericCombine[Int,Float]
weightedSum(lst)
in a local variable before invoking the function needing it doesn't seem to have any impact. So why is it being picked up by the implicit system.
Just use
def plus[A: Numeric,B:Numeric](x: A, y: B): NumericCombine[A,B]#AB
Note the # (hash) instead of . (dot). This is called "type projection". Dot notation is called "path dependent type". I'm telling you these names so that you can google for more info easily. Simply put, # is used for accessing types from classes/traits, and . is used for accessing types from objects/values.
Example:
trait Foo {
type T
}
val fooObj: Foo = new Foo {
type T = Int
}
type t1 = fooObj.T
type t2 = Foo#T
* 18 Apr 2017: updated base on the latest code from author *
* 19 Apr 2017 *
Add NumericCombine#Implicits for convinence
Remove AnyVal constraints to support any Numeric types e.g. BigInt
Refactor NumericCombine
You need Aux pattern:
import scala.collection.GenSeq
trait NumericCombine[A, B] {
type AB
def fromA(x: A): AB
def fromB(y: B): AB
val numericA: Numeric[A]
val numericB: Numeric[B]
val numericAB: Numeric[AB]
// For convenience, caller can 'import combine.Implicits._'
// to bring the Numeric's into the current scope
object Implicits {
implicit def implicitNumericA = numericA
implicit def implicitNumericB = numericB
implicit def implicitNumericAB = numericAB
}
def plus(x: A, y: B): AB = numericAB.plus(fromA(x), fromB(y))
def minus(x: A, y: B): AB = numericAB.minus(fromA(x), fromB(y))
def times(x: A, y: B): AB = numericAB.times(fromA(x), fromB(y))
}
object NumericCombine {
type Aux[A, B, _AB] = NumericCombine[A, B] {
type AB = _AB
}
private def combine[A, B, _AB](fa: A => _AB, fb: B => _AB)
(implicit
_numericA: Numeric[A],
_numericB: Numeric[B],
_numericAB: Numeric[_AB]
): NumericCombine[A, B] = new NumericCombine[A, B] {
override type AB = _AB
override def fromA(x: A): AB = fa(x)
override def fromB(y: B): AB = fb(y)
override val numericA: Numeric[A] = _numericA
override val numericB: Numeric[B] = _numericB
override val numericAB: Numeric[AB] = _numericAB
}
implicit lazy val IntFloat = combine[Int, Float, Float](_.toFloat, identity)
implicit lazy val BigIntBigDecimal = combine[BigInt, BigDecimal, BigDecimal](i => BigDecimal(i), identity)
}
implicit class ValuesWithWeight[A, B](val weightedValue: (A, B)) {
def weight: A = weightedValue._1
def value: B = weightedValue._2
}
def weightedSum[A, B, AB]
(valuesWithWeight: GenSeq[(A, B)])
(implicit combine: NumericCombine.Aux[A, B, AB]):
(A, AB) = {
import combine.Implicits._
val z: (A, AB) =
(combine.numericA.zero, combine.numericAB.zero)
def accumulateWeightedValue(accum: (A, AB), valueWithWeight: (A, B)): (A, AB) = {
val weightedValue = combine.times(valueWithWeight.weight, valueWithWeight.value)
(
combine.numericA.plus(accum.weight, valueWithWeight.weight),
combine.numericAB.plus(accum.value, weightedValue)
)
}
valuesWithWeight.aggregate(z)(
accumulateWeightedValue,
// dataOps.tuple2.plus[A,AB]
{
case ((a1, ab1), (a2, ab2)) =>
(combine.numericA.plus(a1, a2) ->
combine.numericAB.plus(ab1, ab2))
}
)
}
weightedSum(Seq(1 -> 1.5f, 2 -> 1f, 3 -> 1.7f))
weightedSum(Seq(BigInt(1) -> BigDecimal("1.5"), BigInt(2) -> BigDecimal("1"), BigInt(3) -> BigDecimal("1.7")))
An alternative to #slouc's answer is
def plus[A, B](x: A, y: B)(implicit ev: NumericCombine[A, B]): ev.AB
I'd also enhance NumericCombine:
trait NumericCombine[A, B] {
type AB <: AnyVal
def fromA(a: A): AB
def fromB(b: B): AB
val num: Numeric[AB]
}
abstract class NumericCombineImpl[A, B, R](implicit val num: Numeric[R], f1: A => R, f2: B => R) {
type AB = R
def fromA(a: A) = f1(a)
def fromB(b: B) = f2(b)
}
implicit object IntFloat extends NumericCombineImpl[Int,Float,Float]
...
This would allow to actually implement plus, no casts required:
def plus[A, B](x: A, y: B)(implicit ev: NumericCombine[A, B]): ev.AB =
ev.num.plus(ev.fromA(x), ev.fromB(y))

Pulling out shapeless polymorphic functions that have dependencies

New to shapeless and I have a question on using polymorphic functions that need some dependencies. I basically have this code and want to pull somePoly object out of the run method:
import shapeless._
object SomeObject {
type SomeType = Int :+: String :+: (String, Int) :+: CNil
def run( someList: List[SomeType], someInt:Int, someWord:String ) = {
object somePoly extends Poly1 {
implicit def doIt = at[Int]( i => i + someInt + someWord.length)
implicit def doIt2 = at[String]( i => i.length + someWord.length)
implicit def doIt3 = at[(String, Int)]( i => i._1.length + someWord.length)
}
someList.map( _.map(somePoly) )
}
}
One way I thought of doing it was like this, but it seems messy:
object TypeContainer {
type SomeType = Int :+: String :+: (String, Int) :+: CNil
}
case class SomePolyWrapper( someList: List[TypeContainer.SomeType], someInt:Int, someWord:String ){
object somePoly extends Poly1 {
implicit def doIt = at[Int]( i => i + someInt + someWord.length)
implicit def doIt2 = at[String]( i => i.length + someWord.length)
implicit def doIt3 = at[(String, Int)]( i => i._1.length + someWord.length)
}
}
object SomeObject {
def run( someList: List[TypeContainer.SomeType], someInt:Int, someWord:String ) = {
val somePolyWrapper = SomePolyWrapper(someList, someInt, someWord)
someList.map( _.map(somePolyWrapper.somePoly) )
}
}
Anyone have any advice?
The limitations of Scala's implicit resolution system mean the Poly definition needs to be a stable identifier, which makes this kind of thing more painful than it should be. As I mentioned on Gitter, there are a couple of workarounds that I know of (there may be others).
One approach would be to make the Poly1 a PolyN, where the extra arguments are for the someInt and someWord values. If you were mapping over an HList, you'd then use mapConst and zip to make the input HList have the right shape. I've never done this for a coproduct, but something similar is likely to work.
Another approach is to use a custom type class. In your case that might look something like this:
import shapeless._
trait IntFolder[C <: Coproduct] {
def apply(i: Int, w: String)(c: C): Int
}
object IntFolder {
implicit val cnilIntFolder: IntFolder[CNil] = new IntFolder[CNil] {
def apply(i: Int, w: String)(c: CNil): Int = sys.error("Impossible")
}
def instance[H, T <: Coproduct](f: (H, Int, String) => Int)(implicit
tif: IntFolder[T]
): IntFolder[H :+: T] = new IntFolder[H :+: T] {
def apply(i: Int, w: String)(c: H :+: T): Int = c match {
case Inl(h) => f(h, i, w)
case Inr(t) => tif(i, w)(t)
}
}
implicit def iif[T <: Coproduct: IntFolder]: IntFolder[Int :+: T] =
instance((h, i, w) => h + i + w.length)
implicit def sif[T <: Coproduct: IntFolder]: IntFolder[String :+: T] =
instance((h, i, w) => h.length + i + w.length)
implicit def pif[T <: Coproduct: IntFolder]: IntFolder[(String, Int) :+: T] =
instance((h, i, w) => h._1.length + i + w.length)
}
And then you could write a more generic version of your run:
def run[C <: Coproduct](
someList: List[C],
someInt: Int,
someWord: String
)(implicit cif: IntFolder[C]): List[Int] = someList.map(cif(someInt, someWord))
And use it like this:
scala> run(List(Coproduct[SomeType](1)), 10, "foo")
res0: List[Int] = List(14)
scala> run(List(Coproduct[SomeType](("bar", 1))), 10, "foo")
res1: List[Int] = List(16)
The specificity of the operation makes this approach look a little weird, but if I really needed to do something like this for different coproducts, this is probably the solution I'd choose.

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.

How to implement an heterogeneous container in Scala

I need an heterogeneous, typesafe container to store unrelated type A, B, C.
Here is a kind of type-level specification :
trait Container {
putA(a: A)
putB(b: B)
putC(c: C)
put(o: Any) = { o match {
case a: A => putA(a)
case b: B => putB(b)
case c: C => putC(c)
}
getAllAs : Seq[A]
getAllBs : Seq[B]
getAllCs : Seq[C]
}
Which type is best suites to backed this container ?
Is it worth creating a Containerable[T] typeclass for types A, B, C ?
thks.
As other have suggested, you can leverage shapeless' Coproduct type. Here's an example.
// let's define a Coproduct of the two types you want to support
type IS = Int :+: String :+: CNil
// now let's have a few instances
val i = Coproduct[IS](42)
val i2 = Coproduct[IS](43)
val s = Coproduct[IS]("foo")
val s2 = Coproduct[IS]("bar")
// let's put them in a container
val cont = List(i, s, i2, s2)
// now, do you want all the ints?
val ints = cont.map(_.select[Int]).flatten
// or all the strings?
val strings = cont.map(_.select[String]).flatten
// and of course you can add elements (it's a List)
val cont2 = Coproduct[IS](12) :: cont
val cont3 = Coproduct[IS]("baz") :: cont2
Now this is of course not the most intuitive API for a generic container, but can easily encapsulate the logic inside a custom class using a Coproduct for representing the multiple types.
Here's a sketch of an implementation
import shapeless._; import ops.coproduct._
class Container[T <: Coproduct] private (underlying: List[T]) {
def ::[A](a: A)(implicit ev: Inject[T, A]) =
new Container(Coproduct[T](a) :: underlying)
def get[A](implicit ev: Selector[T, A]) =
underlying.map(_.select[A]).flatten
override def toString = underlying.toString
}
object Container {
def empty[T <: Coproduct] = new Container(List[T]())
}
Example
scala> type IS = Int :+: String :+: CNil
defined type alias IS
scala> val cont = 42 :: "foo" :: "bar" :: 43 :: Container.empty[IS]
cont: Container[IS] = List(42, foo, bar, 43)
scala> cont.get[Int]
res0: List[Int] = List(42, 43)
scala> cont.get[String]
res1: List[String] = List(foo, bar)
Miles Sabin wrote a post on unboxed union types; this is implemented as a CoProduct in his shapeless library:
shapeless has a Coproduct type, a generalization of Scala's Either to an arbitrary number of choices
I am definitely not an expert on shapeless, but if you create a new question with or edit your question with the shapeless tag then you can get any assistance needed with using CoProduct
You should look at Shapeless's HList or Coproduct; I wouldn't reinvent this myself.
Here is a first version, but I would to abstract over type :
trait Container {
def putInt(i: Int)
def putString(s: String)
def put(o: Any) = o match {
case i: Int => putInt(i)
case s: String => putString(s)
}
def getInts() : Seq[Int]
def getStrings() : Seq[String]
}
class MutableContainer extends Container {
val ints = mutable.ArrayBuffer[Int]()
val strings = mutable.ArrayBuffer[String]()
override def putInt(i: Int): Unit = ints += i
override def putString(s: String): Unit = strings += s
override def getStrings(): Seq[String] = strings
override def getInts(): Seq[Int] = ints
}
object TestContainer extends App {
val mc = new MutableContainer()
mc.put("a")
mc.put("b")
mc.put(1)
println(mc.getInts())
println(mc.getStrings())
}
Now trying to abstract over type
trait Container {
def getInts() : Seq[Int]
def getStrings() : Seq[String]
def put[T](t: T)
//def get[T] : Seq[T]
}
class MutableContainer extends Container {
val entities = new mutable.HashMap[Class[_], mutable.Set[Any]]() with mutable.MultiMap[Class[_], Any]
override def getStrings(): Seq[String] = entities.get(classOf[String]).map(_.toSeq).getOrElse(Seq.empty).asInstanceOf[Seq[String]] //strings
override def getInts(): Seq[Int] = entities.get(classOf[Int]).map(_.toSeq).getOrElse(Seq.empty).asInstanceOf[Seq[Int]]
//override def get[T]: Seq[T] = entities.get(classOf[T]).map(_.toSeq).getOrElse(Seq.empty).asInstanceOf[Seq[T]]
override def put[T](t: T): Unit = entities.addBinding(t.getClass, t)
}
trait Containable[T] {
def typ : String
}
trait Cont {
implicit object IntContainable extends Containable[Int] {
override def typ: String = "Int"
}
implicit object StringContainable extends Containable[String] {
override def typ: String = "String"
}
}
object TestContainer extends App {
val mc = new MutableContainer()
mc.put("a")
mc.put("b")
mc.put(1)
println(mc.getInts())
println(mc.getStrings())
println(mc.entities.keys)
}
But i've got a problem with java.lang.Integer and Int…