fix documentation of type heirarchy
[gitmo/Moose.git] / lib / Moose / Manual / Types.pod
index 8d6d8f0..1b54e65 100644 (file)
@@ -1,27 +1,28 @@
-=pod
+package Moose::Manual::Types;
+
+# ABSTRACT: Moose's type system
 
-=head1 NAME
+__END__
 
-Moose::Manual::Types - Moose's Type System
+=pod
 
 =head1 TYPES IN PERL?
 
-Moose provides its own type system for your class's attributes. You
-can also use these types to validate method parameters with the help
-of some MooseX modules.
+Moose provides its own type system for attributes. You can also use
+these types to validate method parameters with the help of a MooseX
+module.
 
 Moose's type system is based on a combination of Perl 5's own
-I<implicit> types, and some Perl 6 concepts as well. But most
-importantly, you can easily create your own subtypes with custom
-constraints, making it easy to express any sort of validation.
+I<implicit> types and some Perl 6 concepts. You can create your
+own subtypes with custom constraints, making it easy to express any
+sort of validation.
 
-You can also name types and re-use them by name, making it easy to
+Types have names, and you can re-use them by name, making it easy to
 share types throughout a large application.
 
-Let us be clear that is not a "real" type system. Moose does not
-magically make Perl start associating types with variables. In many
-ways, this is really an advanced parameter checking system which
-allows you to associate a name with a constraintq.
+However, this is not a "real" type system. Moose does not magically make Perl
+start associating types with variables. This is just an advanced parameter
+checking system which allows you to associate a name with a constraint.
 
 That said, it's still pretty damn useful, and we think it's one of the
 things that makes Moose both fun and powerful. Taking advantage of the
@@ -33,33 +34,60 @@ data, and it also contributes greatly to code maintainability.
 The basic Moose type hierarchy looks like this
 
   Any
-  Item
-      Bool
-      Maybe[`a]
-      Undef
-      Defined
-          Value
-              Num
-                Int
-              Str
-                ClassName
-          Ref
-              ScalarRef
-              ArrayRef[`a]
-              HashRef[`a]
-              CodeRef
-              RegexpRef
-              GlobRef
-                FileHandle
-              Object
-                Role
+      Item
+          Bool
+          Maybe[`a]
+          Undef
+          Defined
+              Value
+                  Str
+                      Num
+                          Int
+                      ClassName
+                      RoleName
+              Ref
+                  ScalarRef[`a]
+                  ArrayRef[`a]
+                  HashRef[`a]
+                  CodeRef
+                  RegexpRef
+                  GlobRef
+                  FileHandle
+                  Object
 
 In practice, the only difference between C<Any> and C<Item> is
 conceptual. C<Item> is used as the top-level type in the hierarchy.
 
-The rest of these types correspond to existing Perl concepts. For
-example, a C<Num> is anything that Perl thinks looks like a number. An
-C<Object> is a blessed reference, etc.
+The rest of these types correspond to existing Perl concepts.
+In particular:
+
+=over 4
+
+=item
+
+C<Bool> accepts C<1> for true, and undef, 0, or the empty string as false.
+
+=item
+
+C<Maybe[`a]> accepts either C<`a> or C<undef>.
+
+=item
+
+C<Num> accepts anything that perl thinks looks like a number (see L<Scalar::Util/looks_like_number>).
+
+=item
+
+C<ClassName> and C<RoleName> accept strings that are either the name of a class or the name of a role. The class/role must already be loaded when the constraint is checked.
+
+=item
+
+C<FileHandle> accepts either an L<IO::Handle> object or a builtin perl filehandle (see L<Scalar::Util/openhandle>).
+
+=item
+
+C<Object> accepts any blessed reference.
+
+=back
 
 The types followed by "[`a]" can be parameterized. So instead of just
 plain C<ArrayRef> we can say that we want C<ArrayRef[Int]> instead. We
@@ -68,7 +96,7 @@ can even do something like C<HashRef[ArrayRef[Str]]>.
 The C<Maybe[`a]> type deserves a special mention. Used by itself, it
 doesn't really mean anything (and is equivalent to C<Item>). When it
 is parameterized, it means that the value is either C<undef> or the
-parameterized type. So C<Maybe[Int]> means an integer or C<undef>
+parameterized type. So C<Maybe[Int]> means an integer or C<undef>.
 
 For more details on the type hierarchy, see
 L<Moose::Util::TypeConstraints>.
@@ -77,9 +105,9 @@ L<Moose::Util::TypeConstraints>.
 
 It's important to realize that types are not classes (or
 packages). Types are just objects (L<Moose::Meta::TypeConstraint>
-objects, to be exact) with a name. Moose maintains a global type
-registry that lets it convert names like "Num" into the appropriuate
-object.
+objects, to be exact) with a name and a constraint. Moose maintains a
+global type registry that lets it convert names like C<Num> into the
+appropriate object.
 
 However, class names I<can be> type names. When you define a new class
 using Moose, it defines an associated type name behind the scenes:
@@ -91,7 +119,7 @@ using Moose, it defines an associated type name behind the scenes:
 Now you can use C<'MyApp::User'> as a type name:
 
   has creator => (
-      is  => 'rw',
+      is  => 'ro',
       isa => 'MyApp::User',
   );
 
@@ -101,7 +129,7 @@ assumes that any unknown type name passed as the C<isa> value for an
 attribute is a class. So this works:
 
   has 'birth_date' => (
-      is  => 'rw',
+      is  => 'ro',
       isa => 'DateTime',
   );
 
@@ -118,59 +146,45 @@ that the name is a class:
       isa => 'ArrayRef[DateTime]',
   );
 
-Moose will assume that "DateTime" is a class name and create a type
-accordingly.
+Moose will assume that C<DateTime> is a class name in both of these
+instances.
 
 =head1 SUBTYPES
 
-Moose uses subtypes in its built-in hierarchy. C<Int> is a child of
-C<Num> for example.
+Moose uses subtypes in its built-in hierarchy. For example, C<Int> is
+a child of C<Num>.
 
 A subtype is defined in terms of a parent type and a constraint. Any
-constraints defined by the parent(s) will be checked first, and then
-the subtype's constraint is checked. A value must pass I<all> of these
+constraints defined by the parent(s) will be checked first, followed by
+constraints defined by the subtype. A value must pass I<all> of these
 checks to be valid for the subtype.
 
-Generally, a subtype takes the parent's constraint and makes it more
+Typically, a subtype takes the parent's constraint and makes it more
 specific.
 
 A subtype can also define its own constraint failure message. This
 lets you do things like have an error "The value you provided (20),
 was not a valid rating, which must be a number from 1-10." This is
 much friendlier than the default error, which just says that the value
-failed a validation check for the type.
+failed a validation check for the type. The default error can, however,
+be made more friendly by installing L<Devel::PartialDump> (version 0.14 or
+higher), which Moose will use if possible to display the invalid value.
 
 Here's a simple (and useful) subtype example:
 
-  subtype 'PositiveInt'
-      => as 'Int'
-      => where { $_ > 0 }
-      => message { "The number you provided, $_, was not a positive number" }
+  subtype 'PositiveInt',
+      as 'Int',
+      where { $_ > 0 },
+      message { "The number you provided, $_, was not a positive number" };
 
 Note that the sugar functions for working with types are all exported
 by L<Moose::Util::TypeConstraints>.
 
-=head2 Creating a New Type (That Isn't a Subtype)
-
-You can also create new top-level types:
-
-  type 'FourCharacters' => where { defined $_ && length $_ == 4 };
-
-In practice, this example is pretty much the same as doing the same
-thing as a subtype of C<Str>, except you have to check defined-ness
-yourself.
-
-It's hard to find a case where you wouldn't want to subtype a very
-broad type like C<Defined>, C<Ref> or C<Object>.
-
-In practice, defining a new top-level type is conceptually the same as
-subtyping C<Item>.
-
 =head1 TYPE NAMES
 
 Type names are global throughout the current Perl
-interpreter. Internally, Moose maps names to type objects via
-L<Moose::Meta::TypeConstraint::Registry|registry> singleton.
+interpreter. Internally, Moose maps names to type objects via a
+L<registry|Moose::Meta::TypeConstraint::Registry>.
 
 If you have multiple apps or libraries all using Moose in the same
 process, you could have problems with collisions. We recommend that
@@ -178,43 +192,51 @@ you prefix names with some sort of namespace indicator to prevent
 these sorts of collisions.
 
 For example, instead of calling a type "PositiveInt", call it
-"MyApp.Type.PositiveInt".
+"MyApp::Type::PositiveInt" or "MyApp::Types::PositiveInt". We
+recommend that you centralize all of these definitions in a single
+package, C<MyApp::Types>, which can be loaded by other classes in your
+application.
+
+However, before you do this, you should look at the L<MooseX::Types>
+module. This module makes it easy to create a "type library" module, which can
+export your types as perl constants.
+
+  has 'counter' => (is => 'rw', isa => PositiveInt);
 
-Type names are just strings, and can contain any character you
-want. We recommend that you I<do not> use "::" as a separator in type
-names. This can be very confusing, because class names are I<also>
-valid type names! Using something else, like a period, makes it clear
-that "MyApp::User" is a class and "MyApp.Type.PositiveInt" is a Moose
-type defined by your application.
+This lets you use a short name rather than needing to fully qualify the name
+everywhere. It also allows you to easily create parameterized types:
 
-The C<MooseX::Types> module lets you create bareword aliases to longer
-names (really, the barewords are functions).
+  has 'counts' => (is => 'ro', isa => HashRef[PositiveInt]);
+
+This module will check your names at compile time, and is generally more
+robust than the string type parsing for complex cases.
 
 =head1 COERCION
 
-One of the most powerful features of Moose's type system is its
-coercions. A coercion is a mapping between two types.
+A coercion lets you tell Moose to automatically convert one type to another.
+
+  subtype 'ArrayRefOfInts',
+      as 'ArrayRef[Int]';
 
-  subtype 'ArrayRefOfInts'
-      => as 'ArrayRef[Int]';
+  coerce 'ArrayRefOfInts',
+      from 'Int',
+      via { [ $_ ] };
 
-  coerce 'ArrayRefOfInts'
-      => from 'Int'
-      => via { [ $_ ] };
+You'll note that we created a subtype rather than coercing C<ArrayRef[Int]>
+directly. It's a bad idea to add coercions to the raw built in
+types.
 
-You'll note that we had to create a subtype rather than coercing
-C<ArrayRef[Int]> directly. This is just a quirk of how Moose
-works.
+Coercions are global, just like type names, so a coercion applied to a built
+in type is seen by all modules using Moose types. This is I<another> reason
+why it is good to namespace your types.
 
-Coercions, like type names, are global. This is I<another> reason why
-it is good to namespace your types. Moose will I<never> try to coerce
-a value unless you explicitly ask for it. This is done by setting the
-C<coerce> attribute parameter to a true value:
+Moose will I<never> try to coerce a value unless you explicitly ask for
+it. This is done by setting the C<coerce> attribute option to a true value:
 
   package Foo;
 
   has 'sizes' => (
-      is     => 'rw',
+      is     => 'ro',
       isa    => 'ArrayRefOfInts',
       coerce => 1,
   );
@@ -224,56 +246,55 @@ C<coerce> attribute parameter to a true value:
 This code example will do the right thing, and the newly created
 object will have C<[ 42 ]> as its C<sizes> attribute.
 
-=head2 Deep Coercion
+=head2 Deep coercion
 
 Deep coercion is the coercion of type parameters for parameterized
 types. Let's take these types as an example:
 
-  subtype 'HexNum'
-      => as 'Str'
-      => where { /[a-f0-9]/i };
+  subtype 'HexNum',
+      as 'Str',
+      where { /[a-f0-9]/i };
 
-  coerce 'Int'
-      => from 'HexNum'
-      => via { hex $_ };
+  coerce 'Int',
+      from 'HexNum',
+      via { hex $_ };
 
   has 'sizes' => (
-      is     => 'rw',
+      is     => 'ro',
       isa    => 'ArrayRef[Int]',
       coerce => 1,
   );
 
 If we try passing an array reference of hex numbers for the C<sizes>
-attribute, Moose will not do any coercion. The reason for this is that
-it gets very complicate very fast.
+attribute, Moose will not do any coercion.
 
-However, if you want to, you can define a set of subtypes to enable
-coercion between two parameterized types.
+However, you can define a set of subtypes to enable coercion between
+two parameterized types.
 
-  subtype 'ArrayRefOfHexNums'
-      => as 'ArrayRef[HexNum]';
+  subtype 'ArrayRefOfHexNums',
+      as 'ArrayRef[HexNum]';
 
-  subtype 'ArrayRefOfInts'
-      => as 'ArrayRef[Int]';
+  subtype 'ArrayRefOfInts',
+      as 'ArrayRef[Int]';
 
-  coerce 'ArrayRefOfInts'
-      => from 'ArrayRefOfHexNums'
-      => via { [ map { hex } @{$_} ] };
+  coerce 'ArrayRefOfInts',
+      from 'ArrayRefOfHexNums',
+      via { [ map { hex } @{$_} ] };
 
   Foo->new( sizes => [ 'a1', 'ff', '22' ] );
 
 Now Moose will coerce the hex numbers to integers.
 
-However, Moose does not attempt to chain coercions, so we cannot pass
-a single hex number. If we want to make that possible as well, we need
-to define yet another coercion:
+Moose does not attempt to chain coercions, so it will not
+coerce a single hex number. To do that, we need to define a separate
+coercion:
 
-  coerce 'ArrayRefOfInts'
-      => from 'HexNum'
-      => via { [ hex $_ ] };
+  coerce 'ArrayRefOfInts',
+      from 'HexNum',
+      via { [ hex $_ ] };
 
 Yes, this can all get verbose, but coercion is tricky magic, and we
-think it's best to make it as explicit as possible.
+think it's best to make it explicit.
 
 =head1 TYPE UNIONS
 
@@ -291,15 +312,13 @@ a type union. The C<output> attribute will accept any sort of object,
 as well as an unblessed file handle. It is up to you to do the right
 thing for each of them in your code.
 
-Whenever you consider using a type union, you should think about
-whether or not coercion might be a better answer.
+Whenever you use a type union, you should consider whether or not
+coercion might be a better answer.
 
 For our example above, we might want to be more specific, and insist
 that output be an object with a C<print> method:
 
-  subtype 'CanPrint'
-      => as 'Object'
-      => where { $_->can('print') };
+  duck_type 'CanPrint', [qw(print)];
 
 We can coerce file handles to an object that satisfies this condition
 with a simple wrapper class:
@@ -309,7 +328,7 @@ with a simple wrapper class:
   use Moose;
 
   has 'handle' => (
-      is  => 'ro',
+      is  => 'rw',
       isa => 'FileHandle',
   );
 
@@ -317,12 +336,12 @@ with a simple wrapper class:
       my $self = shift;
       my $fh   = $self->handle();
 
-      print $fh @_;
+      print {$fh} @_;
   }
 
 Now we can define a coercion from C<FileHandle> to our wrapper class:
 
-  coerce 'FHWrapper'
+  coerce 'CanPrint'
       => from 'FileHandle'
       => via { FHWrapper->new( handle => $_ ) };
 
@@ -332,33 +351,32 @@ Now we can define a coercion from C<FileHandle> to our wrapper class:
       coerce => 1,
   );
 
-This pattern, using a coercion instead of a type union, can help
-simplify the use of the attribute, and should be considered whenever
-you have a type union.
+This pattern of using a coercion instead of a type union will help
+make your class internals simpler.
 
 =head1 TYPE CREATION HELPERS
 
 The L<Moose::Util::TypeConstraints> module exports a number of helper
 functions for creating specific kinds of types. These include
-C<class_type>, C<role_type>, and C<maybe_type>. See the docs for
-details.
+C<class_type>, C<role_type>, C<maybe_type>, and C<duck_type>. See the
+docs for details.
 
 One helper worth noting is C<enum>, which allows you to create a
 subtype of C<Str> that only allows the specified values:
 
-  enum 'RGB' => qw( red green blue );
+  enum 'RGB', [qw( red green blue )];
 
-This creates a type named C<RGB>
+This creates a type named C<RGB>.
 
 =head1 ANONYMOUS TYPES
 
 All of the type creation functions return a type object. This type
 object can be used wherever you would use a type name, as a parent
-type, or as the value for an attribute's C<isa> parameter:
+type, or as the value for an attribute's C<isa> option:
 
   has 'size' => (
-      is => 'rw',
-      isa => subtype 'Int' => where { $_ > 0 },
+      is  => 'ro',
+      isa => subtype( 'Int' => where { $_ > 0 } ),
   );
 
 This is handy when you want to create a one-off type and don't want to
@@ -370,7 +388,7 @@ Moose does not provide any means of validating method
 parameters. However, there are several MooseX extensions on CPAN which
 let you do this.
 
-The simplest and least sugary is C<MooseX::Params::Validate>. This
+The simplest and least sugary is L<MooseX::Params::Validate>. This
 lets you validate a set of named parameters using Moose types:
 
   use Moose;
@@ -378,54 +396,32 @@ lets you validate a set of named parameters using Moose types:
 
   sub foo {
       my $self   = shift;
-      my %params = validate(
+      my %params = validated_hash(
           \@_,
           bar => { isa => 'Str', default => 'Moose' },
       );
       ...
   }
 
-C<MooseX::Params::Validate> also supports coercions.
+L<MooseX::Params::Validate> also supports coercions.
 
 There are several more powerful extensions that support method
 parameter validation using Moose types, including
-C<MooseX::Method::Signatures>, which gives you a full-blown C<method>
+L<MooseX::Method::Signatures>, which gives you a full-blown C<method>
 keyword.
 
-  method morning (Str $name) {
+  method morning ( Str $name ) {
       $self->say("Good morning ${name}!");
   }
 
 =head1 LOAD ORDER ISSUES
 
-Because Moose types are defined at runtime, you can sometimes run into
-issues with load order. In particular, you may sometimes want to use a
-class's type constraint before it exists.
-
-We recommend several things. First, define I<all> of your custom types
-in one module, C<MyApp::Types>. Second, load this module in all of
-your other modules.
-
-If you are still having load order problems, you can make use of the
-C<find_type_constraint> function exported by
-L<Moose::Util::TypeConstraints>:
-
-  my $type = find_type_constraint('MyApp::User') || class_type('MyApp::User');
-
-This sort of "find or create" logic is simple to write, and will let
-you work around load order issues.
-
-=head1 AUTHOR
-
-Dave Rolsky E<lt>autarch@urth.orgE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2008 by Infinity Interactive, Inc.
-
-L<http://www.iinteractive.com>
+Because Moose types are defined at runtime, you may run into load
+order problems. In particular, you may want to use a class's type
+constraint before that type has been defined.
 
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
+In order to ameliorate this problem, we recommend defining I<all> of your
+custom types in one module, C<MyApp::Types>, and then loading this module in
+all of your other modules.
 
 =cut