Attention: (Update 2016-12-08) The forSome keyword is very likely going away with Scala 2.13 or 2.14, according to Martin Odersky’s talk on the ScalaX 2016. Replace it with path dependent types or with anonymous type attributes (A[_]
). This is possible in most cases. If you have an edge case where it is not possible, refactor your code or loosen your type restrictions.
How to read “forSome” (in an informal way)
Usually when you use a generic API, the API guarantees you, that it will work with any type you provide (up to some given constraints). So when you use List[T]
, the List API guarantees you that it will work with any type T
you provide.
With forSome
(so called existentially quantified type parameters) it is the other way round. The API will provide a type (not you) and it guarantees you, it will work with this type it provided you. The semantics is, that a concrete object will give you something of type T
. The same object will also accept the things it provided you. But no other object may work with these T
s and no other object can provide you with something of type T
.
The idea of “existentially quantified” is: There exists (at least) one type T
(in the implementation) to fulfill the contract of the API. But I won’t tell you which type it is.
forSome
can be read similar: For some types T
the API contract holds true. But it is not necessary true for all types T
. So when you provide some type T
(instead of the one hidden in the implementation of the API), the compiler cannot guarantee that you got the right T
. So it will throw a type error.
Applied to your example
So when you see List[T] forSome {type T}
in an API, you can read it like this: The API will provide you with a List
of some unknown type T
. It will gladly accept this list back and it will work with it. But it won’t tell you, what T
is. But you know at least, that all elements of the list are of the same type T
.
The second one is a little bit more tricky. Again the API will provide you with a List
. And it will use some type T
and not tell you what T
is. But it is free to choose a different type for each element. A real world API would establish some constraints for T
, so it can actually work with the elements of the list.
Conclusion
forSome
is useful, when you write an API, where each object represents an implementation of the API. Each implementation will provide you with some objects and will accept these objects back. But you can neither mix objects from different implementations nor can you create the objects yourself. Instead you must always use the corresponding API functions to get some objects that will work with that API. forSome
enables a very strict kind of encapsulation. You can read forSome
in the following way:
The API contract folds true for some types. But you don’t know for
which types it holds true. Hence you cannot provide you own type and
you cannot create your own objects. You have to use the ones provided
through the API that usesforSome
.
This is quite informal and might even be wrong in some corner cases. But it should help you to grok the concept.