X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMooseX%2FDependent%2FTypes.pm;h=c08f822f62930200d7be2cda82848c797598074b;hb=26cf337eb5c6275eddbcda39f7187416d6314b2f;hp=57000a2e4f0b059834074165b1348a4f1f0e335f;hpb=9c319add216c3b774b1740bf98b1a1f8492dc1c0;p=gitmo%2FMooseX-Dependent.git diff --git a/lib/MooseX/Dependent/Types.pm b/lib/MooseX/Dependent/Types.pm index 57000a2..c08f822 100644 --- a/lib/MooseX/Dependent/Types.pm +++ b/lib/MooseX/Dependent/Types.pm @@ -152,55 +152,71 @@ is a capacity we current don't have. =head2 Coercions -You can place coercions on dependent types, however you need to pay attention to -what you are actually coercion, the unparameterized or parameterized constraint. - - TBD: Need discussion and example of coercions working for both the - constrainted and dependent type constraint. +Dependent types have some limited support for coercions. Several things must +be kept in mind. The first is that the coercion targets the type constraint +which is being made dependent, Not the dependent type. So for example if you +create a Dependent type like: + + subtype RequiredAgeInYears, + as Int; + + subtype PersonOverAge, + as Dependent[Person, RequiredAgeInYears] + where { + my ($person, $required_years_old) = @_; + return $person->years_old > $required_years_old; + } + +This would validate the following: + + my $person = Person->new(age=>35); + PersonOverAge([18])->check($person); - subtype OlderThanAge, - as Dependent[Int, Dict[older_than=>Int]], +You can then apply the following coercion + + coerce PersonOverAge, + from Dict[age=>int], + via {Person->new(%$_)}, + from Int, + via {Person->new(age=>$_)}; + +This coercion would then apply to all the following: + + PersonOverAge([18])->check(30); ## via the Int coercion + PersonOverAge([18])->check({age=>50}); ## via the Dict coercion + +However, you are not allowed to place coercions on dependent types that have +had their constraining value filled, nor subtypes of such. For example: + + coerce PersonOverAge[18], + from DateTime, + via {$_->years}; + +That would generate a hard exception. This is a limitation for now until I can +devise a smarter way to cache the generated type constraints. However, I doubt +it will be a significant limitation, since the general use case is supported. + +Lastly, the constraining value is available in the coercion in much the same way +it is available to the constraint. + + ## Create a type constraint where a Person must be in the set + subtype PersonInSet, + as Dependent[Person, PersonSet], where { - my ($value, $dict) = @_; - return $value > $dict->{older_than} ? 1:0; - }; - -Which should work like: - - OlderThanAge([{older_than=>25}])->check(39); ## is OK - OlderThanAge([older_than=>1])->check(9); ## OK, using reference type inference - -And you can create coercions like: + my ($person, $person_set) = @_; + $person_set->find($person); + } - coerce OlderThanAge, - from Tuple[Int, Int], + coerce PersonInSet, + from HashRef, via { - my ($int, $int); - return [$int, {older_than=>$int}]; + my ($hashref, $person_set) = @_; + return $person_set->create($hash_ref); }; =head2 Recursion -Newer versions of L support recursive type constraints. That is -you can include a type constraint as a contained type constraint of itself. -Recursion is support in both the dependent and constraining type constraint. For -example, if we assume an Object hierarchy like Food -> [Grass, Meat] - - TODO: DOES THIS EXAMPLE MAKE SENSE? - - subtype Food, - as Dependent[Food, Food], - where { - my ($value, $allowed_food_type) = @_; - return $value->isa($allowed_food_type); - }; - - my $grass = Food::Grass->new; - my $meat = Food::Meat->new; - my $vegetarian = Food[$grass]; - - $vegetarian->check($grass); ## Grass is the allowed food of a vegetarian - $vegetarian->check($meat); ## BANG, vegetarian can't eat meat! + TBD =head1 TYPE CONSTRAINTS