Thursday 14 June 2012

Scala: undocumented

There are interesting undocumented classes which are helping to restrict applicability for the methods coming with Generics Types. They are useful to restrain the type parameter in therms of single method. Lets review them in details and compare with Type Parameterization.


<:<[A, B] or sugar via A <:< B

The compiler is providing an implicit instance of this type only if A is the subtype of B. This is almost similar to B >: A in a type parameter list ( def func[B >: A](b: B) )
It was invented when class owner needs to put one more constraint for class parameter in therms of single method. Scala doc help a lot on understanding: 
"An instance of `A <:< B` witnesses that `A` is a subtype of `B`. Requiring an implicit argument of the type `A <:< B` encodes the generalized constraint `A <: B`... To constrain any abstract type T that's in scope in a method's argument list (not just the method's own type parameters) simply add an implicit argument of type `T <:< U`, where U is the required upper bound; or for lower-bounds, use: `L <:< T`, where L is the required lower bound."

For example:
And the way how we are using func1 brings predictable results: Lets call restricted func2: Error message is quite detailed to understand the problem. To make it work we should do elicit casting of String to Any type: I mentioned that it is almost equaled to to B >: A . Lets review example to find the differences: and putting the String to func3 doesn't produce compilation and runtime problems: As we can see the main difference between the parameterization and <:< Class that type inference "feature" of compiler brings to the less strict check from parameterization. Few scala lines to refresh on type inference, bellow an example which is showing that String is Any in the same time:

=:=[A,B] (sugar A =:= B)

This one is very simple and doesn't have parameterization analogue. The compiler can provide an implicit instance of this type only when A is exactly the same type as B.the best example is when Class declares type T extends Numbers, but some methods requires exact realisations (Int or Float):
and How to use it:

<%<[A,B] (sugar A <%< B)

Implicit parameter is provided (by Compiler) only in case of A can be converted to B. This is representing the A <% B in a type's parameter list. I see it has been deprecated (@deprecated("Use From => To instead", "2.9.0")) and A => B contraction is recommended.

2 comments:

  1. Thanks for the post! My doubts:

    1. Why did you choose to declare the constraint as an implicit and also pass "e" to the function. By intuition if we pass an argument to a function, it should be used in the function body, isn't it?

    2. Can the same objective be achieved by "context bound" approach?

    3. Can we create our own custom type constraints like the three you have discussed above? How can they be hooked to the compiler?

    ReplyDelete