How to pass an implicit parameter from an instance? - scala

I'm trying to define a class which will have as a field a Set, and would like to be able to manipulate this set directly from the container class:
case class MyClass(prop: String) extends TraversableLike[Int,MyClass] {
private def mySet: Set[Int]() = Set()
override def foreach[U](f: Int => U) = data.foreach[U](f)
override def newBuilder: Builder[Int, MyClass] =
new ArrayBuffer[Int] mapResult (a => MyClass(prop, a.toSet))
implicit def canBuildFrom: CanBuildFrom[MyClass, Int, MyClass] =
new CanBuildFrom[MyClass, Int, MyClass] {
def apply(): Builder[Int, MyClass] = newBuilder
def apply(from: MyClass): Builder[Int, MyClass] = newBuilder
}
}
I'd like to be able to do
var obj = MyClass("hello")
obj += 1
obj = obj map (_+1)
The first instruction (obj+= 1) works, but the second doesn't.
The problem is that I can't put my implicit canBuildFrom into an object MyClass because builder needs informations dependant of the instance (in this case, the prop field).
Is there a solution make my implicit accessible and keep its instance dependance ?
I'd like to avoid making my class mutable.

There are a couple of problems with your code:
Set[Int]() is not a valid type for mySet, you should drop the ()
member mySet should be a val, not a def
you are calling apply() methods that don't exist
if you want to hook in into the collections hierarchy at the Traversable level, you don't get methods like + and the derived +=. If you're representing a set, then it should be a Set.
Here's a revised attempt:
import mutable.Builder
import generic.CanBuildFrom
class MyClass private (val prop: String, private val mySet: Set[Int] = Set())
extends immutable.Set[Int] with SetLike[Int, MyClass] {
def -(elem: Int) = MyClass(prop, mySet - elem)
def +(elem: Int) = MyClass(prop, mySet + elem)
def contains(elem: Int) = mySet.contains(elem)
def iterator = mySet.iterator
override def empty: MyClass = MyClass(prop)
override def stringPrefix = "MyClass(" + prop + ")"
}
object MyClass {
def DefaultProp = "DefaultProp"
def apply(prop: String, mySet: Set[Int] = Set()) = new MyClass(prop, mySet)
def newBuilder(prop: String = DefaultProp): Builder[Int, MyClass] =
Set.newBuilder[Int] mapResult (set => MyClass(prop, set))
implicit def canBuildFrom: CanBuildFrom[MyClass, Int, MyClass] =
new CanBuildFrom[MyClass, Int, MyClass] {
def apply(): Builder[Int, MyClass] = newBuilder()
def apply(from: MyClass): Builder[Int, MyClass] = newBuilder(from.prop)
}
}
Then you can write:
var obj = MyClass("hello")
obj += 1
println(obj) // prints MyClass(hello)(1)
obj = obj map (_ + 1)
println(obj) // prints MyClass(hello)(2)
Let's dissect that:
MyClass is now explicitly an immutable set with a custom representation declared in the type arguments to SetLike. prop is a public val member; the actual set, mySet, is a private val.
Then we need to implement the four operations on which Set relies, by simply forwarding them the mySet. (This looks a like it could be factored out. For the Seqs, there is a class SeqForwarder that does a similar job; I couldn't find a SetForwarder, though). Finally, we provide an empty method, on which the built-in inherited builder also relies. Finally, overriding stringPrefix enables a nicer string representation with "MyClass" and the value of prop.
Note that The canBuildFrom object MyClass calls newBuilder, passing the prop of the original collection when it can. This means that most of the time, you can keep this value while mapping, etc. over MyClass instances. We need to define a default value for prop, however, since CanBuildFroms must define an apply method that does not tell what the originating collection is. (Question: why would this actually happen?)
Finally, our implementation of newBuilder does not rely on ArrayBuffers any more, but directly builds the Set instance that will be wrapped by your new MyClass instance.
Some more resources:
http://www.scala-lang.org/docu/files/collections-api/collections-impl.html
Implement a scala collection so that map, filter, etc. produce the right type

Related

How to extend an immutable collection and add a field member?

I would like to add a member someProperty to an immutable Set like this,
class MySet[A](val someProperty: T, set: Set[A])
extends Set[A] with SetLike[A, MySet[A]] {
//...
}
such that MySet behaves like a Set. However, I am not clever enough to implement a Builder/CanBuildFrom (eg. here) that would retain someProperty following a transformation. My only solution is to manually wire up MySet with map, foldLeft, etc., such that it behaves like a Set
class MySet[A](val someProperty: T, set: Set[A]) {
def map[B](f: (A) => B)(implicit bf: CanBuildFrom[Set[A], B, Set[B]]): MySet[B] =
new MySet[B](someProperty, set.map[B, Set[B]](f)(bf))
//more methods here...
}
but this seems very tedious. Is there a better way to do this without getting into mutable territory? Thanks.
First of all, having a default (zero) value for someProperty makes things a bit easier. In your case, I guess you could choose Must or MustNot, depending on the specifics of your problem.
I'll assume the following definition of T and its default:
sealed trait T
object T {
final val Default: T = Must
}
case object Must extends T
case object MustNot extends T
case object Should extends T
You can have the following implementation for MySet, deferring most operations to its set attribute, and some to its companion object. Also, note that some methods like filter don't use CanBuildFrom, so you have to override newBuilder method for them.
class MySet[A](val someProperty: T, set: Set[A])
extends Set[A] with SetLike[A, MySet[A]] {
def +(elem: A): MySet[A] = new MySet[A](someProperty, set + elem)
def -(elem: A): MySet[A] = new MySet[A](someProperty, set - elem)
def contains(elem: A): Boolean = set contains elem
def iterator: Iterator[A] = set.iterator
override def companion = MySet
override def empty: MySet[A] = MySet.empty[A]
// Required for `filter`, `take`, `drop`, etc. to preserve `someProperty`.
override def newBuilder: mutable.Builder[A, MySet[A]] =
MySet.newBuilder[A](someProperty)
}
As for the companion object MySet, it's possible to extend SetFactory[MySet] or some other base class of collection companion objects. This gives implementations of MySet.empty[A] and MySet.apply[A](as: A*), which create MySet using the default value of someProperty.
object MySet extends SetFactory[MySet] {
// For the builder you can defer to the standard `mutable.SetBuilder`
class MySetBuilder[A](someProperty: T) extends
mutable.SetBuilder[A, MySet[A]](new MySet(someProperty, Set.empty))
def newBuilder[A] = newBuilder[A](T.Default)
// Additional method for creating a builder with a known value of `someProperty`
def newBuilder[A](someProperty: T) = new MySetBuilder[A](someProperty)
// You may also want to define `apply` and `empty` methods
// that take a known `someProperty`.
// `CanBuildFrom` from `MySet[_]` to `MySet[A]`.
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, MySet[A]] =
new CanBuildFrom[Coll, A, MySet[A]] {
// This is the method that makes
// e.g. `map`, `flatMap`, `collect` preserve `someProperty`
def apply(from: Coll): mutable.Builder[A, MySet[A]] =
newBuilder[A](from.someProperty)
def apply(): mutable.Builder[A, MySet[A]] = newBuilder[A]
}
}

How to check I'm inside a #specialized function or class at runtime in scala?

Let's say I have a specialized class and an associated companion object:
trait Slice[#specialized +T] {
...
override def equals(that :Any) = that match {
case s :Slice[_] => ???
case _ => false
}
}
object Slice {
def newInstance[#specialized T] = ???
}
Is there any way to check
Inside a method of Slice if this instance is a specialized subclass,
Inside a method of Slice if another instance is a specialized subclass for the same primitive,
Inside a specialized method on a companion object if I'm running an erased or specialized variant
without resorting to ClassTags or passing Class[_] manually? It seems like that information should be available, but the only way I can think of involves checking names of the classes.
Use case 2) is particularly important, as I could resort to faster algorithms if I knew I'm comparing apples with apples. It probably could be accomplished by reflection, but it would be quite tricky when you take into account that we have to handle non-synthetic subclasses of Slice, too; if we have also
trait ArraySlice[#specialized T] extends Slice[T] { ... }
that should be considered 'compatible' with Slice[T] instances as long as they are both specialized (or both erased)?
Ok, I figured out a cleaner way:
final val AllButUnit = new Specializable.Group((Byte, Short, Int, Long, Char, Float, Double, Boolean, AnyRef))
def specializationFor[#specialized(AllButUnit) E] :ResolvedSpecialization[E] =
Specializations(new SpecializedKey[E]).asInstanceOf[ResolvedSpecialization[E]]
private val Specializations = Seq(
resolve[Byte],
resolve[Short],
resolve[Int],
resolve[Long],
resolve[Char],
resolve[Float],
resolve[Double],
resolve[Boolean],
resolve[Unit],
resolve[AnyRef]
).map(
spec => spec.key -> spec :(SpecializedKey[_], ResolvedSpecialization[_])
).toMap.withDefaultValue(resolve[AnyRef])
private def resolve[#specialized(AllButUnit) E :ClassTag] :ResolvedSpecialization[E] =
new ResolvedSpecialization[E](new SpecializedKey[E], new Array[E](0))
class ResolvedSpecialization[#specialized(AllButUnit) E] private[SpecializedCompanion]
(val array :Array[E], val elementType :Class[E], val classTag :ClassTag[E], private[SpecializedCompanion] val key :SpecializedKey[E])
{
private[SpecializedCompanion] def this(key :SpecializedKey[E], array :Array[E]) =
this(array, array.getClass.getComponentType.asInstanceOf[Class[E]], ClassTag(array.getClass.getComponentType.asInstanceOf[Class[E]]), key)
override def toString = s"#specialized($elementType)"
override def equals(that :Any) = that match {
case r :ResolvedSpecialization[_] => r.elementType==elementType
case _ => false
}
override def hashCode = elementType.hashCode
}
private class SpecializedKey[#specialized(AllButUnit) E] {
override def equals(that :Any) = that.getClass==getClass
override def hashCode = getClass.hashCode
def className = getClass.getName
override def toString = className.substring(className.indexOf("$")+1)
}
Now specializationFor[E].elementType returns class corresponding to specialization parameter of E.

A method in Scala that takes no arguments and uses a generic type

I'm trying to write a method in Scala that will take no arguments and will use a generic type to perform some logic in the method that will return output solely based on the generic type (similar to asInstanceOf[T] or isInstanceOf[T]).
It should be something like this:
val myObj = new MyClass
myObj.instanceOf[MyClass]
// returns true
This is what I thought may work.
class MyClass {
def instanceOf[Class[_]]: Bool = {
// ???
}
}
How do I implement this?
Thank you.
You could grab the type that was passed in by using ClassTags and use that.
A contrived example of what is asked in the title would be:
class Foo(name: String) {
def nameMatches[T: ClassTag]() =
classTag[T].runtimeClass.getName == name
}
new Foo("java.lang.String").nameMatches[String] //> res1: Boolean = true
new Foo("boolean").nameMatches[Boolean] //> res2: Boolean = true
This will work for the example you gave.
import scala.reflect.runtime.universe._
class MyClass {
def instanceOf[T: TypeTag] = typeOf[this.type] <:< typeOf[T]
}
Note that when you extend MyClass you will need to override instanceOf to get correct behaviour. Else you will get this:
scala> class MySubClass extends MyClass
defined class MySubClass
scala> (new MySubClass).instanceOf[MyClass] // works
res3: Boolean = true
scala> (new MySubClass).instanceOf[Any] // works
res4: Boolean = true
scala> (new MySubClass).instanceOf[MySubClass] // doesn't work
res5: Boolean = false
Another example of a generic method would be the standard library's implicitly, which you can trivially implement yourself:
def implicitly[T](implicit ev: T) = ev
so you can do things like look up type class instances:
trait Show[T] { def shows(t: T): String }
case class Person(name: String, age: Int)
implicit val personShow = new Show[Person] { def show(p: Person) = s"${p.name} # ${p.age} years" }
implicitly[Show[Person]]
this is useful in two cases:
you define a non-trivial type class instance using def (i.e. you generically "generate" type class instances from instances of other type classes) and you're not sure you got it right:
implicit def terriblyNonTrivialTCInstance[T, U, V, W, Ñ](implicit ev1: Foo, ev2: Bar, ev3: Baz, ...): FooTC[T, U] = ...
implicitly[FooTC[MyType1, MyType2]] // compile error if the above definition is badly constructed
your method takes an implicit evidence but instead of using an implicit arg list, you prefer to use a type bound, and later you'd like to grab an instance of the type class using implicitly:
def myMethod[T: FooTC[T, Int]](t: T) = {
val ev = implicitly[FooTC[T, Int]]
ev.doSmth(t)
}
instead of:
def myMehtod[T](t: T)(implicit ev: FooTC[T, Int]) = {
ev.doSmth(t)
}
P.S. in the stdlib, implicitly is implemented like this:
#inline def implicitly[T](implicit e: T) = e

A case class as a "wrapper" class for a collection. What about map/foldLeft/

What I try to do is to come up with a case class which I can use in pattern matching which has exactly one field, e.g. an immutable set. Furthermore, I would like to make use of functions like map, foldLeft and so on which should be passed down to the set. I tried it as in the following:
case class foo(s:Set[String]) extends Iterable[String] {
override def iterator = s.iterator
}
Now if I try to make use of e.g. the map function, I get an type error:
var bar = foo(Set() + "test1" + "test2")
bar = bar.map(x => x)
found : Iterable[String]
required: foo
bar = bar.map(x => x)
^
The type error is perfectly fine (in my understanding). However, I wonder how one would implement a wrapper case class for a collection such that one can call map, foldLeft and so on and still receive an object of the case class. Would one need to override all these functions or is there some other way around?
Edit
I'm inclined to accept the solution of Régis Jean-Gilles which works for me. However, after Googling for hours I found another interesting Scala trait named SetProxy. I couldn't find any trivial examples so I'm not sure if this trait does what I want:
come up with a custom type, i.e. a different type than Set
the type must be a case class (we want to do pattern matching)
we need "delegate" methods map, foldLeft and so on which should pass the call to our actual set and return the resulting set wrapped arround in our new type
My first idea was to extend Set but my custom type Foo already extends another class. Therefore, the second idea was to mixin the trait Iterable and IterableLike. Now I red about the trait SetProxy which made me think about which is "the best" way to go. What are your thoughts and experiences?
Since I started learning Scala three days ago, any pointers are highly appreciated!
Hmm this sounds promissing to me but Scala says that variable b is of type Iterable[String] and not of type Foo, i.e. I do not see how IterableLike helps in this situation
You are right. Merely inheriting from IterableLike as shown by mpartel will make the return type of some methods more precise (such as filter, which will return Foo), but for others such as map of flatMap you will need to provide an appopriate CanBuildFrom implicit.
Here is a code snippet that does just that:
import collection.IterableLike
import collection.generic.CanBuildFrom
import collection.mutable.Builder
case class Foo( s:Set[String] ) extends Iterable[String] with IterableLike[String, Foo] {
override def iterator = s.iterator
override protected[this] def newBuilder: scala.collection.mutable.Builder[String, Foo] = new Foo.FooBuilder
def +(elem: String ): Foo = new Foo( s + elem )
}
object Foo {
val empty: Foo = Foo( Set.empty[String] )
def apply( elems: String* ) = new Foo( elems.toSet )
class FooBuilder extends Builder[String, Foo] {
protected var elems: Foo = empty
def +=(x: String): this.type = { elems = elems + x; this }
def clear() { elems = empty }
def result: Foo = elems
}
implicit def canBuildFrom[T]: CanBuildFrom[Foo, String, Foo] = new CanBuildFrom[Foo, String, Foo] {
def apply(from: Foo) = apply()
def apply() = new FooBuilder
}
}
And some test in the repl:
scala> var bar = Foo(Set() + "test1" + "test2")
bar: Foo = (test1, test2)
scala> bar = bar.map(x => x) // compiles just fine because map now returns Foo
bar: Foo = (test1, test2)
Inheriting IterableLike[String, Foo] gives you all those methods such that they return Foo. IterableLike requires you to implement newBuilder in addition to iterator.
import scala.collection.IterableLike
import scala.collection.mutable.{Builder, SetBuilder}
case class Foo(stuff: Set[String]) extends Iterable[String] with IterableLike[String, Foo] {
def iterator: Iterator[String] = stuff.iterator
protected[this] override def newBuilder: Builder[String, Foo] = {
new SetBuilder[String, Set[String]](Set.empty).mapResult(Foo(_))
}
}
// Test:
val a = Foo(Set("a", "b", "c"))
val b = a.map(_.toUpperCase)
println(b.toList.sorted.mkString(", ")) // Prints A, B, C

creating a new instance of a type in scala

If I have a class C defined as
class C[A]
is there any way to create a new instance of A within C? Something like
class C[A] {
def f(): A = new A()
}
I understand that, if this were possible, you'd probably have to specify the constructor arguments somewhere, and that's fine.
If it's not possible, are there any design patterns for dealing with the sort of situation where you'd like to create a new instance of a type?
You could use a type class to abstract instantiation:
trait Makeable[T] {
def make: T
}
class C[T: Makeable] {
def f(): T = implicitly[Makeable[T]].make
}
For example,
implicit object StringIsMakeable extends Makeable[String] {
def make: String = "a string"
}
val c = new C[String]
c.f // == "a string"
When you instantiate C, you'll need to provide, explicitly or implicitly, a Makeable that will act as a factory of the appropriate type. That factory, of course, would be responsible for supplying any constructor arguments when it invokes the constructor.
Alternatively, you could use a Manifest, but be warned that this approach relies on reflection and is not type safe:
class C[T: Manifest] {
def f(): T = manifest[T].erasure.newInstance.asInstanceOf[T]
}
For completeness, you can also easily extend this approach to pass some or all of the constructor parameters in to the make method:
trait Makeable[Args, T] { def make(a: Args): T }
class C[Args, T](implicit e: Makeable[Args, T]) {
def f(a: Args): T = e.make(a)
}
// some examples
case class Person(firstName: String, lastName: String)
implicit val personFactory1 = new Makeable[(String, String), Person] {
def make(a: (String, String)): Person = Person(a._1, a._2)
}
implicit val personFactory2 = new Makeable[String, Person] {
def make(a: String): Person = Person(a, "Smith")
}
val c1 = new C[String, Person]
c1.f("Joe") // returns Person("Joe", "Smith")
val c2 = new C[(String, String), Person]
c2.f("John", "Smith") // returns Person("John", "Smith")
You can demand an implicit parameter, like so:
class A[T](implicit newT : T) {
val t = newT
}
All you need then is to have an implicit factory of the desired type in scope when you instanciate A, e.g. the following works:
implicit def newSeq[T] = Seq[T]()
val a = new A[Seq[String]]
As shown by:
scala> a.t
res22: Seq[String] = List()
The same as #Raphael's answer with a case class's apply method:
class Container[A](contained: A)
case class Person(name: String)
case class PersonContainer(person: Person) extends Container[Person](person)
implicit def _ = PersonContainer.apply _
class Creator {
def deserializeAndPackage[A, B <: Container[A]](data: Array[Byte])
(implicit containerCreator: (A => B)): B = {
val p = /* deserialize data as type of A */
containerCreator(p)
}
}