MooseX::Types is an alternative method for creating an managing your Moose type constraints. This has been recently updated to properly support parameterized type constraints and type constrain unions. So now you can correctly do:
subtype MyArrayRefOfIntegers,
as ArrayRef[Int];
subtype BigInt,
as Int,
where { $_ >10 };
subtype MyArrayRefOfBigInts,
as MyArrayRefOfIntegers[BigInt];
So there are a few things going on here. First of all “MyArrayRefOfIntegers” is defined as a parameterized ArrayRef and will match [1,2,3, ...] but not ['a','b','c', …] since that data structure contains strings. We also created a subtype called “BigInt” which is an integer with a further requirement that the value be greater than 10. Granted, you may not consider this very big, but it will serve for example. Then, we define another type constraint which is a subtype of the previously created parameterized type. We call this one, “MyArrayRefOfBigInts”, since it extends the “MyArrayRefOfIntegers” subtype with a new type parameter, the previously created “BigInt”. This will match [11,12,13, ...], but not [1,2,3, …], since the latter violates the “BigInt” constraint. This ability for a parameterized type subtype it's type parameter is a recent addition to Moose, so you'll need at least the 0.60 version.
If you extend a parameterized subtype this way, the new type parameter must be a subtype of the type parameter of the parent type. So this could be any subtype of “Int” but not “Str”. If you try, you'll get an error.
Please note you could have done the following to achieve the same effect:
subtype MyArrayRefOfBigInts,
as MyArrayRefOfIntegers,
where { foreach my $int (@$_) {$int > 10 || return 0} 1 };
However, I believe the first example is cleaner and offers additional reusability.
Type constraint unions are straightforward:
subtype MyThisOrThat,
as Int|Str;
This would match either an Int or a Str type constraint. Personally, I don't use these type of constraints very much since I suspect they may indicate improper abstraction at some level, but to each her own. Of course can can mix and match:
subtype MyBigMess,
as HashRef[HashRef[Num|Object]|ArrayRef[Str|Object]];
However at some point you need to start wondering if what you are doing is sane :)
If you are using MooseX::Types in your applications, please update to the latest and let me know if you find any problems.