Published 2012-08-06.
Time to read: 2 minutes.
For Scala programmers, the term 'existential types' does not refer to philosophers, or even authentic people. Ironically, most of the discussions of Scala's existential types that I found are too abstract to be useful to me. I learn by doing; rarely do I learn from reading an abstract treatise. I guess this means that I could be labelled an existentialist.
Section 31.3 of Programming in Scala has some good information on Scala's existential types. Existential types is an abstraction of Java types, and abstraction is the antithesis of existentialism... aaaanyway, here is a sentence I stole from the book:
Iterator[_]
means the same thing as Iterator[T] forSome { type T }
forSome
is the keyword which tells the compiler that an existential type is being defined.
This becomes useful if upper and/or lower bounds are used to define the type.
For example, you can use a lower bound to specify that the type must be a subclass of PubSubAction
with the following existential type:
T forSome { type T <: PubSubAction }
That is a lot of characters, so let's give this type a name:
type PubSubActionSubclass = T forSome { type T <: PubSubAction }
We can also define a type to help us with SalatDAO
:
type SalatObject = T forSome { type T <: AnyRef }
Now lets use SalatObject
as the parametric type for an invocation of Manifest.classType()
:
val mot = Manifest.classType[SalatObject](msg.getClass)
This is useful because the manifest can be passed to a
SalatDAO
constructor, which will create a DAO object for whatever type is supplied.
In the following code, PubSubActionClass
is just used to guarantee that the msg
parameter is of the correct type;
SalatDAO
's constructor is defined to accept all subclasses of AnyRef
.
import com.novus.salat.global.ctx abstract class PubSubAction object PubSubAction { def makeDAO[PubSubActionSubclass](msg: PubSubActionSubclass) (implicit coll: MongoCollection) = { val mot = Manifest.classType[SalatObject](msg.getClass) val mid = Manifest.classType[Int](classOf[Int]) new SalatDAO(coll)(mot, mid, ctx){} } }
Now you know that you do not have to hard-code the creation of a DAO for every PubSubAction
subclass.
You can examine the
source code for SalatDAO
if you would like to learn more.
Assuming that psaMsg
is an instance of a PubSubActionSubclass
, you could call insert()
as follows to do a generic insert.
Because Salat has multiple methods called insert()
,
there is not enough type information for Scala to disambiguate the method reference unless
the returned value from the single insert is stored in a variable,
and that variable's type is provided:
val ignoredIndex: Option[Int] = makeDAO.insert(psaMsg)
There is only one variant of insert()
which accepts a collection, so the reference is not ambiguous and the return value can be ignored:
dao.insert(Seq(psaMsg, psaMsg2, psaMsg3), WriteConcern.Normal)