Jesse Schalken wrote on 21/04/2016 04:18:
Sticking with your example for a moment, if the type parameter is an
"int", then the only type that can /currently/ be expressed in the
type language that is a subtype of "int" is "int", so it's not very
useful /right now/. However, a possible introduction of integer
literal types would change that, especially in combination with
unions. This would enable you to express the type "1|2|3", i.e. only
one of those three integers. This would be useful to typecheck enums,
which are typically an "int" or "string" which only accepts a finite
set of values. As such, the type parameter "T is int" could be filled
with "int" or "1" or "0|1|2". (Imagine a class "Bar<T is int>" and
various subclasses which each must select a single integer as kind of
tag, "Foo extends Bar<1>", "Baz extends Bar<2>" etc. I do this in
TypeScript with string literal types all the time.)
I'm struggling to follow this example; it seems like you are using the
type parameter to supply actual data to the implementation, which goes
rather beyond generics, and into full-blown template metaprogramming.
I'm not sure why you'd ever need the sub-class to compile in a value
that way rather than just overriding a method somewhere, and would need
some convincing that PHP needed this kind of complexity.
Beside from that, the introduction of any one of union types,
intersection types, generic array types or callable types would mean
the type constraint for a generic type can usefully be something
besides a single class/interface. For example, if "<T is
array|Travarsable>" were written "<T instanceof array|Traversable>" I
would expect to be able to do "$t instanceof array|Traversable", but I
wouldn't be able to unless "instanceof" is intended to and is extended
to support arbitrary types.
This is a stronger argument, although I think extending the instanceof
operator might be a good idea in that case anyway - otherwise, we would
have a constraint that you can assert (produce a TypeError at a function
boundary) but not easily test for. To avoid replicating the engine's
entire checking routine, you'd end up doing this:
function ugly_instance_of<T>($value): boolean {
try {
return (function(T $checked) { return true; })($value);
}
catch ( TypeError $e ) {
return false;
}
}
if ( ugly_instance_of<array<Foo>>($x) ) // if ( $x instanceof array<Foo> )
*shudder* ;)
Regards,
--
Rowan Collins
[IMSoP]