fixing a bug for Sartak
[gitmo/Moose.git] / lib / Moose / Util / TypeConstraints.pm
1
2 package Moose::Util::TypeConstraints;
3
4 use strict;
5 use warnings;
6
7 use Carp         'confess';
8 use Scalar::Util 'blessed', 'reftype';
9 use B            'svref_2object';
10 use Sub::Exporter;
11
12 our $VERSION   = '0.17';
13 our $AUTHORITY = 'cpan:STEVAN';
14
15 ## --------------------------------------------------------
16 # Prototyped subs must be predeclared because we have a
17 # circular dependency with Moose::Meta::Attribute et. al.
18 # so in case of us being use'd first the predeclaration
19 # ensures the prototypes are in scope when consumers are
20 # compiled.
21
22 # creation and location
23 sub find_type_constraint                 ($);
24 sub find_or_create_type_constraint       ($;$);
25 sub create_type_constraint_union         (@);
26 sub create_parameterized_type_constraint ($);
27
28 # dah sugah!
29 sub type        ($$;$$);
30 sub subtype     ($$;$$$);
31 sub coerce      ($@);
32 sub as          ($);
33 sub from        ($);
34 sub where       (&);
35 sub via         (&);
36 sub message     (&);
37 sub optimize_as (&);
38 sub enum        ($;@);
39
40 ## private stuff ...
41 sub _create_type_constraint ($$$;$$);
42 sub _install_type_coercions ($$);
43
44 ## --------------------------------------------------------
45
46 use Moose::Meta::TypeConstraint;
47 use Moose::Meta::TypeConstraint::Union;
48 use Moose::Meta::TypeConstraint::Parameterized;
49 use Moose::Meta::TypeCoercion;
50 use Moose::Meta::TypeCoercion::Union;
51 use Moose::Meta::TypeConstraint::Registry;
52
53 my @exports = qw/
54     type subtype as where message optimize_as
55     coerce from via
56     enum
57     find_type_constraint
58 /;
59
60 Sub::Exporter::setup_exporter({
61     exports => \@exports,
62     groups  => { default => [':all'] }
63 });
64
65 sub unimport {
66     no strict 'refs';
67     my $class = caller();
68     # loop through the exports ...
69     foreach my $name (@exports) {
70         # if we find one ...
71         if (defined &{$class . '::' . $name}) {
72             my $keyword = \&{$class . '::' . $name};
73
74             # make sure it is from Moose
75             my $pkg_name = eval { svref_2object($keyword)->GV->STASH->NAME };
76             next if $@;
77             next if $pkg_name ne 'Moose::Util::TypeConstraints';
78
79             # and if it is from Moose then undef the slot
80             delete ${$class . '::'}{$name};
81         }
82     }
83 }
84
85 ## --------------------------------------------------------
86 ## type registry and some useful functions for it
87 ## --------------------------------------------------------
88
89 my $REGISTRY = Moose::Meta::TypeConstraint::Registry->new;
90
91 sub get_type_constraint_registry         { $REGISTRY }
92 sub list_all_type_constraints            { keys %{$REGISTRY->type_constraints} }
93 sub export_type_constraints_as_functions {
94     my $pkg = caller();
95     no strict 'refs';
96     foreach my $constraint (keys %{$REGISTRY->type_constraints}) {
97         *{"${pkg}::${constraint}"} = $REGISTRY->get_type_constraint($constraint)
98                                               ->_compiled_type_constraint;
99     }
100 }
101
102 sub create_type_constraint_union (@) {
103     my @type_constraint_names;
104
105     if (scalar @_ == 1 && _detect_type_constraint_union($_[0])) {
106         @type_constraint_names = _parse_type_constraint_union($_[0]);
107     }
108     else {
109         @type_constraint_names = @_;
110     }
111
112     (scalar @type_constraint_names >= 2)
113         || confess "You must pass in at least 2 type names to make a union";
114
115     ($REGISTRY->has_type_constraint($_))
116         || confess "Could not locate type constraint ($_) for the union"
117             foreach @type_constraint_names;
118
119     return Moose::Meta::TypeConstraint::Union->new(
120         type_constraints => [
121             map {
122                 $REGISTRY->get_type_constraint($_)
123             } @type_constraint_names
124         ],
125     );
126 }
127
128 sub create_parameterized_type_constraint ($) {
129     my $type_constraint_name = shift;
130
131     my ($base_type, $type_parameter) = _parse_parameterized_type_constraint($type_constraint_name);
132
133     (defined $base_type && defined $type_parameter)
134         || confess "Could not parse type name ($type_constraint_name) correctly";
135
136     ($REGISTRY->has_type_constraint($base_type))
137         || confess "Could not locate the base type ($base_type)";
138
139     return Moose::Meta::TypeConstraint::Parameterized->new(
140         name           => $type_constraint_name,
141         parent         => $REGISTRY->get_type_constraint($base_type),
142         type_parameter => find_or_create_type_constraint(
143             $type_parameter => {
144                 parent     => $REGISTRY->get_type_constraint('Object'),
145                 constraint => sub { $_[0]->isa($type_parameter) }
146             }
147         ),
148     );
149 }
150
151 sub find_or_create_type_constraint ($;$) {
152     my ($type_constraint_name, $options_for_anon_type) = @_;
153
154     return $REGISTRY->get_type_constraint($type_constraint_name)
155         if $REGISTRY->has_type_constraint($type_constraint_name);
156
157     my $constraint;
158
159     if (_detect_type_constraint_union($type_constraint_name)) {
160         $constraint = create_type_constraint_union($type_constraint_name);
161     }
162     elsif (_detect_parameterized_type_constraint($type_constraint_name)) {
163         $constraint = create_parameterized_type_constraint($type_constraint_name);
164     }
165     else {
166         # NOTE:
167         # if there is no $options_for_anon_type 
168         # specified, then we assume they don't 
169         # want to create one, and return nothing.
170         return unless defined $options_for_anon_type;        
171
172         # NOTE:
173         # otherwise assume that we should create
174         # an ANON type with the $options_for_anon_type
175         # options which can be passed in. It should
176         # be noted that these don't get registered
177         # so we need to return it.
178         # - SL
179         return Moose::Meta::TypeConstraint->new(
180             name => '__ANON__',
181             %{$options_for_anon_type}
182         );
183     }
184
185     $REGISTRY->add_type_constraint($constraint);
186     return $constraint;
187 }
188
189 ## --------------------------------------------------------
190 ## exported functions ...
191 ## --------------------------------------------------------
192
193 sub find_type_constraint ($) { $REGISTRY->get_type_constraint(@_) }
194
195 # type constructors
196
197 sub type ($$;$$) {
198     splice(@_, 1, 0, undef);
199     goto &_create_type_constraint;
200 }
201
202 sub subtype ($$;$$$) {
203     # NOTE:
204     # this adds an undef for the name
205     # if this is an anon-subtype:
206     #   subtype(Num => where { $_ % 2 == 0 }) # anon 'even' subtype
207     # but if the last arg is not a code
208     # ref then it is a subtype alias:
209     #   subtype(MyNumbers => as Num); # now MyNumbers is the same as Num
210     # ... yeah I know it's ugly code
211     # - SL
212     unshift @_ => undef if scalar @_ <= 2 && (reftype($_[1]) || '') eq 'CODE';
213     goto &_create_type_constraint;
214 }
215
216 sub coerce ($@) {
217     my ($type_name, @coercion_map) = @_;
218     _install_type_coercions($type_name, \@coercion_map);
219 }
220
221 sub as      ($) { $_[0] }
222 sub from    ($) { $_[0] }
223 sub where   (&) { $_[0] }
224 sub via     (&) { $_[0] }
225
226 sub message     (&) { +{ message   => $_[0] } }
227 sub optimize_as (&) { +{ optimized => $_[0] } }
228
229 sub enum ($;@) {
230     my ($type_name, @values) = @_;
231     (scalar @values >= 2)
232         || confess "You must have at least two values to enumerate through";
233     my %valid = map { $_ => 1 } @values;
234     _create_type_constraint(
235         $type_name,
236         'Str',
237         sub { $valid{$_} }
238     );
239 }
240
241 ## --------------------------------------------------------
242 ## desugaring functions ...
243 ## --------------------------------------------------------
244
245 sub _create_type_constraint ($$$;$$) {
246     my $name   = shift;
247     my $parent = shift;
248     my $check  = shift;
249
250     my ($message, $optimized);
251     for (@_) {
252         $message   = $_->{message}   if exists $_->{message};
253         $optimized = $_->{optimized} if exists $_->{optimized};
254     }
255
256     my $pkg_defined_in = scalar(caller(0));
257
258     if (defined $name) {
259         my $type = $REGISTRY->get_type_constraint($name);
260
261         ($type->_package_defined_in eq $pkg_defined_in)
262             || confess ("The type constraint '$name' has already been created in "
263                        . $type->_package_defined_in . " and cannot be created again in "
264                        . $pkg_defined_in)
265                  if defined $type;
266     }
267
268     $parent = find_or_create_type_constraint($parent) if defined $parent;
269     
270     my $constraint = Moose::Meta::TypeConstraint->new(
271         name               => $name || '__ANON__',
272         package_defined_in => $pkg_defined_in,
273
274         ($parent    ? (parent     => $parent )   : ()),
275         ($check     ? (constraint => $check)     : ()),
276         ($message   ? (message    => $message)   : ()),
277         ($optimized ? (optimized  => $optimized) : ()),
278     );
279     
280     # NOTE:
281     # if we have a type constraint union, and no 
282     # type check, this means we are just aliasing
283     # the union constraint, which means we need to 
284     # handle this differently.
285     # - SL
286     if (not(defined($check))
287         && $parent->isa('Moose::Meta::TypeConstraint::Union') 
288         && $parent->has_coercion 
289         ){
290         $constraint->coercion(Moose::Meta::TypeCoercion::Union->new(
291             type_constraint => $parent
292         ));
293     }    
294
295     $REGISTRY->add_type_constraint($constraint)
296         if defined $name;
297
298     return $constraint;
299 }
300
301 sub _install_type_coercions ($$) {
302     my ($type_name, $coercion_map) = @_;
303     my $type = $REGISTRY->get_type_constraint($type_name);
304     if ($type->has_coercion) {
305         $type->coercion->add_type_coercions(@$coercion_map);
306     }
307     else {
308         my $type_coercion = Moose::Meta::TypeCoercion->new(
309             type_coercion_map => $coercion_map,
310             type_constraint   => $type
311         );
312         $type->coercion($type_coercion);
313     }
314 }
315
316 ## --------------------------------------------------------
317 ## type notation parsing ...
318 ## --------------------------------------------------------
319
320 {
321     # All I have to say is mugwump++ cause I know
322     # do not even have enough regexp-fu to be able
323     # to have written this (I can only barely
324     # understand it as it is)
325     # - SL
326
327     use re "eval";
328
329     my $valid_chars = qr{[\w:]};
330     my $type_atom   = qr{ $valid_chars+ };
331
332     my $type                = qr{  $valid_chars+  (?: \[  (??{$any})  \] )? }x;
333     my $type_capture_parts  = qr{ ($valid_chars+) (?: \[ ((??{$any})) \] )? }x;
334     my $type_with_parameter = qr{  $valid_chars+      \[  (??{$any})  \]    }x;
335
336     my $op_union = qr{ \s* \| \s* }x;
337     my $union    = qr{ $type (?: $op_union $type )+ }x;
338
339     our $any = qr{ $type | $union }x;
340
341     sub _parse_parameterized_type_constraint {
342         $_[0] =~ m{ $type_capture_parts }x;
343         return ($1, $2);
344     }
345
346     sub _detect_parameterized_type_constraint {
347         $_[0] =~ m{ ^ $type_with_parameter $ }x;
348     }
349
350     sub _parse_type_constraint_union {
351         my $given = shift;
352         my @rv;
353         while ( $given =~ m{ \G (?: $op_union )? ($type) }gcx ) {
354                 push @rv => $1;
355         }
356         (pos($given) eq length($given))
357             || confess "'$given' didn't parse (parse-pos="
358                      . pos($given)
359                      . " and str-length="
360                      . length($given)
361                      . ")";
362         @rv;
363     }
364
365     sub _detect_type_constraint_union {
366         $_[0] =~ m{^ $type $op_union $type ( $op_union .* )? $}x;
367     }
368 }
369
370 ## --------------------------------------------------------
371 # define some basic built-in types
372 ## --------------------------------------------------------
373
374 type 'Any'  => where { 1 }; # meta-type including all
375 type 'Item' => where { 1 }; # base-type
376
377 subtype 'Undef'   => as 'Item' => where { !defined($_) };
378 subtype 'Defined' => as 'Item' => where {  defined($_) };
379
380 subtype 'Bool'
381     => as 'Item'
382     => where { !defined($_) || $_ eq "" || "$_" eq '1' || "$_" eq '0' };
383
384 subtype 'Value'
385     => as 'Defined'
386     => where { !ref($_) }
387     => optimize_as { defined($_[0]) && !ref($_[0]) };
388
389 subtype 'Ref'
390     => as 'Defined'
391     => where {  ref($_) }
392     => optimize_as { ref($_[0]) };
393
394 subtype 'Str'
395     => as 'Value'
396     => where { 1 }
397     => optimize_as { defined($_[0]) && !ref($_[0]) };
398
399 subtype 'Num'
400     => as 'Value'
401     => where { Scalar::Util::looks_like_number($_) }
402     => optimize_as { !ref($_[0]) && Scalar::Util::looks_like_number($_[0]) };
403
404 subtype 'Int'
405     => as 'Num'
406     => where { "$_" =~ /^-?[0-9]+$/ }
407     => optimize_as { defined($_[0]) && !ref($_[0]) && $_[0] =~ /^-?[0-9]+$/ };
408
409 subtype 'ScalarRef' => as 'Ref' => where { ref($_) eq 'SCALAR' } => optimize_as { ref($_[0]) eq 'SCALAR' };
410 subtype 'ArrayRef'  => as 'Ref' => where { ref($_) eq 'ARRAY'  } => optimize_as { ref($_[0]) eq 'ARRAY'  };
411 subtype 'HashRef'   => as 'Ref' => where { ref($_) eq 'HASH'   } => optimize_as { ref($_[0]) eq 'HASH'   };
412 subtype 'CodeRef'   => as 'Ref' => where { ref($_) eq 'CODE'   } => optimize_as { ref($_[0]) eq 'CODE'   };
413 subtype 'RegexpRef' => as 'Ref' => where { ref($_) eq 'Regexp' } => optimize_as { ref($_[0]) eq 'Regexp' };
414 subtype 'GlobRef'   => as 'Ref' => where { ref($_) eq 'GLOB'   } => optimize_as { ref($_[0]) eq 'GLOB'   };
415
416 # NOTE:
417 # scalar filehandles are GLOB refs,
418 # but a GLOB ref is not always a filehandle
419 subtype 'FileHandle'
420     => as 'GlobRef'
421     => where { Scalar::Util::openhandle($_) }
422     => optimize_as { ref($_[0]) eq 'GLOB' && Scalar::Util::openhandle($_[0]) };
423
424 # NOTE:
425 # blessed(qr/.../) returns true,.. how odd
426 subtype 'Object'
427     => as 'Ref'
428     => where { blessed($_) && blessed($_) ne 'Regexp' }
429     => optimize_as { blessed($_[0]) && blessed($_[0]) ne 'Regexp' };
430
431 subtype 'Role'
432     => as 'Object'
433     => where { $_->can('does') }
434     => optimize_as { blessed($_[0]) && $_[0]->can('does') };
435
436 my $_class_name_checker = sub {
437     return if ref($_[0]);
438     return unless defined($_[0]) && length($_[0]);
439
440     # walk the symbol table tree to avoid autovififying
441     # \*{${main::}{"Foo::"}} == \*main::Foo::
442
443     my $pack = \*::;
444     foreach my $part (split('::', $_[0])) {
445         return unless exists ${$$pack}{"${part}::"};
446         $pack = \*{${$$pack}{"${part}::"}};
447     }
448
449     # check for $VERSION or @ISA
450     return 1 if exists ${$$pack}{VERSION}
451              && defined *{${$$pack}{VERSION}}{SCALAR};
452     return 1 if exists ${$$pack}{ISA}
453              && defined *{${$$pack}{ISA}}{ARRAY};
454
455     # check for any method
456     foreach ( keys %{$$pack} ) {
457         next if substr($_, -2, 2) eq '::';
458         return 1 if defined *{${$$pack}{$_}}{CODE};
459     }
460
461     # fail
462     return;
463 };
464
465 subtype 'ClassName'
466     => as 'Str'
467     => $_class_name_checker # where ...
468     => { optimize => $_class_name_checker };
469
470 ## --------------------------------------------------------
471 # end of built-in types ...
472 ## --------------------------------------------------------
473
474 {
475     my @BUILTINS = list_all_type_constraints();
476     sub list_all_builtin_type_constraints { @BUILTINS }
477 }
478
479 1;
480
481 __END__
482
483 =pod
484
485 =head1 NAME
486
487 Moose::Util::TypeConstraints - Type constraint system for Moose
488
489 =head1 SYNOPSIS
490
491   use Moose::Util::TypeConstraints;
492
493   type 'Num' => where { Scalar::Util::looks_like_number($_) };
494
495   subtype 'Natural'
496       => as 'Num'
497       => where { $_ > 0 };
498
499   subtype 'NaturalLessThanTen'
500       => as 'Natural'
501       => where { $_ < 10 }
502       => message { "This number ($_) is not less than ten!" };
503
504   coerce 'Num'
505       => from 'Str'
506         => via { 0+$_ };
507
508   enum 'RGBColors' => qw(red green blue);
509
510 =head1 DESCRIPTION
511
512 This module provides Moose with the ability to create custom type
513 contraints to be used in attribute definition.
514
515 =head2 Important Caveat
516
517 This is B<NOT> a type system for Perl 5. These are type constraints,
518 and they are not used by Moose unless you tell it to. No type
519 inference is performed, expression are not typed, etc. etc. etc.
520
521 This is simply a means of creating small constraint functions which
522 can be used to simplify your own type-checking code.
523
524 =head2 Slightly Less Important Caveat
525
526 It is almost always a good idea to quote your type and subtype names.
527 This is to prevent perl from trying to execute the call as an indirect
528 object call. This issue only seems to come up when you have a subtype
529 the same name as a valid class, but when the issue does arise it tends
530 to be quite annoying to debug.
531
532 So for instance, this:
533
534   subtype DateTime => as Object => where { $_->isa('DateTime') };
535
536 will I<Just Work>, while this:
537
538   use DateTime;
539   subtype DateTime => as Object => where { $_->isa('DateTime') };
540
541 will fail silently and cause many headaches. The simple way to solve
542 this, as well as future proof your subtypes from classes which have
543 yet to have been created yet, is to simply do this:
544
545   use DateTime;
546   subtype 'DateTime' => as 'Object' => where { $_->isa('DateTime') };
547
548 =head2 Default Type Constraints
549
550 This module also provides a simple hierarchy for Perl 5 types, this
551 could probably use some work, but it works for me at the moment.
552
553   Any
554   Item
555       Bool
556       Undef
557       Defined
558           Value
559               Num
560                 Int
561               Str
562                 ClassName
563           Ref
564               ScalarRef
565               ArrayRef
566               HashRef
567               CodeRef
568               RegexpRef
569               GlobRef
570                 FileHandle
571               Object
572                   Role
573
574 Suggestions for improvement are welcome.
575
576 B<NOTE:> The C<Undef> type constraint does not work correctly
577 in every occasion, please use it sparringly.
578
579 B<NOTE:> The C<ClassName> type constraint is simply a subtype
580 of string which responds true to C<isa('UNIVERSAL')>. This means
581 that your class B<must> be loaded for this type constraint to
582 pass. I know this is not ideal for all, but it is a saner
583 restriction than most others.
584
585 =head2 Use with Other Constraint Modules
586
587 This module should play fairly nicely with other constraint
588 modules with only some slight tweaking. The C<where> clause
589 in types is expected to be a C<CODE> reference which checks
590 it's first argument and returns a bool. Since most constraint
591 modules work in a similar way, it should be simple to adapt
592 them to work with Moose.
593
594 For instance, this is how you could use it with
595 L<Declare::Constraints::Simple> to declare a completely new type.
596
597   type 'HashOfArrayOfObjects'
598       => IsHashRef(
599           -keys   => HasLength,
600           -values => IsArrayRef( IsObject ));
601
602 For more examples see the F<t/204_example_w_DCS.t> test file.
603
604 Here is an example of using L<Test::Deep> and it's non-test
605 related C<eq_deeply> function.
606
607   type 'ArrayOfHashOfBarsAndRandomNumbers'
608       => where {
609           eq_deeply($_,
610               array_each(subhashof({
611                   bar           => isa('Bar'),
612                   random_number => ignore()
613               })))
614         };
615
616 For a complete example see the F<t/205_example_w_TestDeep.t>
617 test file.
618
619 =head1 FUNCTIONS
620
621 =head2 Type Constraint Construction & Locating
622
623 =over 4
624
625 =item B<create_type_constraint_union ($pipe_seperated_types | @type_constraint_names)>
626
627 Given string with C<$pipe_seperated_types> or a list of C<@type_constraint_names>,
628 this will return a L<Moose::Meta::TypeConstraint::Union> instance.
629
630 =item B<create_parameterized_type_constraint ($type_name)>
631
632 Given a C<$type_name> in the form of:
633
634   BaseType[ContainerType]
635
636 this will extract the base type and container type and build an instance of
637 L<Moose::Meta::TypeConstraint::Parameterized> for it.
638
639 =item B<find_or_create_type_constraint ($type_name, ?$options_for_anon_type)>
640
641 This will attempt to find or create a type constraint given the a C<$type_name>.
642 If it cannot find it in the registry, it will see if it should be a union or
643 container type an create one if appropriate, and lastly if nothing can be
644 found or created that way, it will create an anon-type using the
645 C<$options_for_anon_type> HASH ref to populate it. If the C<$options_for_anon_type>
646 is not specified (it is C<undef>), then it will not create anything and simply
647 return.
648
649 =item B<find_type_constraint ($type_name)>
650
651 This function can be used to locate a specific type constraint
652 meta-object, of the class L<Moose::Meta::TypeConstraint> or a
653 derivative. What you do with it from there is up to you :)
654
655 =item B<get_type_constraint_registry>
656
657 Fetch the L<Moose::Meta::TypeConstraint::Registry> object which
658 keeps track of all type constraints.
659
660 =item B<list_all_type_constraints>
661
662 This will return a list of type constraint names, you can then
663 fetch them using C<find_type_constraint ($type_name)> if you
664 want to.
665
666 =item B<list_all_builtin_type_constraints>
667
668 This will return a list of builtin type constraints, meaning,
669 those which are defined in this module. See the section
670 labeled L<Default Type Constraints> for a complete list.
671
672 =item B<export_type_constraints_as_functions>
673
674 This will export all the current type constraints as functions
675 into the caller's namespace. Right now, this is mostly used for
676 testing, but it might prove useful to others.
677
678 =back
679
680 =head2 Type Constraint Constructors
681
682 The following functions are used to create type constraints.
683 They will then register the type constraints in a global store
684 where Moose can get to them if it needs to.
685
686 See the L<SYNOPSIS> for an example of how to use these.
687
688 =over 4
689
690 =item B<type ($name, $where_clause)>
691
692 This creates a base type, which has no parent.
693
694 =item B<subtype ($name, $parent, $where_clause, ?$message)>
695
696 This creates a named subtype.
697
698 =item B<subtype ($parent, $where_clause, ?$message)>
699
700 This creates an unnamed subtype and will return the type
701 constraint meta-object, which will be an instance of
702 L<Moose::Meta::TypeConstraint>.
703
704 =item B<enum ($name, @values)>
705
706 This will create a basic subtype for a given set of strings.
707 The resulting constraint will be a subtype of C<Str> and
708 will match any of the items in C<@values>. It is case sensitive.
709 See the L<SYNOPSIS> for a simple example.
710
711 B<NOTE:> This is not a true proper enum type, it is simple
712 a convient constraint builder.
713
714 =item B<as>
715
716 This is just sugar for the type constraint construction syntax.
717
718 =item B<where>
719
720 This is just sugar for the type constraint construction syntax.
721
722 =item B<message>
723
724 This is just sugar for the type constraint construction syntax.
725
726 =item B<optimize_as>
727
728 This can be used to define a "hand optimized" version of your
729 type constraint which can be used to avoid traversing a subtype
730 constraint heirarchy.
731
732 B<NOTE:> You should only use this if you know what you are doing,
733 all the built in types use this, so your subtypes (assuming they
734 are shallow) will not likely need to use this.
735
736 =back
737
738 =head2 Type Coercion Constructors
739
740 Type constraints can also contain type coercions as well. If you
741 ask your accessor to coerce, then Moose will run the type-coercion
742 code first, followed by the type constraint check. This feature
743 should be used carefully as it is very powerful and could easily
744 take off a limb if you are not careful.
745
746 See the L<SYNOPSIS> for an example of how to use these.
747
748 =over 4
749
750 =item B<coerce>
751
752 =item B<from>
753
754 This is just sugar for the type coercion construction syntax.
755
756 =item B<via>
757
758 This is just sugar for the type coercion construction syntax.
759
760 =back
761
762 =head2 Namespace Management
763
764 =over 4
765
766 =item B<unimport>
767
768 This will remove all the type constraint keywords from the
769 calling class namespace.
770
771 =back
772
773 =head1 BUGS
774
775 All complex software has bugs lurking in it, and this module is no
776 exception. If you find a bug please either email me, or add the bug
777 to cpan-RT.
778
779 =head1 AUTHOR
780
781 Stevan Little E<lt>stevan@iinteractive.comE<gt>
782
783 =head1 COPYRIGHT AND LICENSE
784
785 Copyright 2006, 2007 by Infinity Interactive, Inc.
786
787 L<http://www.iinteractive.com>
788
789 This library is free software; you can redistribute it and/or modify
790 it under the same terms as Perl itself.
791
792 =cut