=pod

=head1 NAME

Moose::Manual::Types - Moose's type system

=head1 TYPES IN PERL?

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. You can easily create your
own subtypes with custom constraints, making it easy to express any
sort of validation.

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. 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
type system makes it much easier to ensure that you are getting valid
data, and it also contributes greatly to code maintainability.

=head1 THE TYPES

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

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 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
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>

For more details on the type hierarchy, see
L<Moose::Util::TypeConstraints>.

=head1 WHAT IS A TYPE?

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 and a constraint. Moose maintains a
global type registry that lets it convert names like "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:

  package MyApp::User;

  use Moose;

Now you can use C<'MyApp::User'> as a type name:

  has creator => (
      is  => 'rw',
      isa => 'MyApp::User',
  );

However, for non-Moose classes there's no magic. You may have to
explicitly declare the class type. This is a bit muddled because Moose
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',
      isa => 'DateTime',
  );

In general, when Moose is presented with an unknown name, it assumes
that the name is a class:

  subtype 'ModernDateTime'
      => as 'DateTime'
      => where { $_->year() >= 1980 }
      => message { 'The date you provided is not modern enough' };

  has 'valid_dates' => (
      is  => 'ro',
      isa => 'ArrayRef[DateTime]',
  );

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.

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 the subtype's. A value must pass I<all> of these checks to be
valid for the subtype.

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.

Here's a simple (and useful) subtype example:

  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 more or less the same as subtyping
C<Str>, except you have to check definedness 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>.

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 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
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".

Type names are just strings. 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.

The L<MooseX::Types> module lets you create bareword aliases to longer
names and also automatically namespaces all the types you define.

=head1 COERCION

One of the most powerful features of Moose's type system is its
coercions. A coercion is a way to convert from one type to another.

  subtype 'ArrayRefOfInts'
      => as 'ArrayRef[Int]';

  coerce 'ArrayRefOfInts'
      => from 'Int'
      => via { [ $_ ] };

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, 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:

  package Foo;

  has 'sizes' => (
      is     => 'rw',
      isa    => 'ArrayRefOfInts',
      coerce => 1,
  );

  Foo->new( sizes => 42 );

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

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 };

  coerce 'Int'
      => from 'HexNum'
      => via { hex $_ };

  has 'sizes' => (
      is     => 'rw',
      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.

However, you can define a set of subtypes to enable coercion between
two parameterized types.

  subtype 'ArrayRefOfHexNums'
      => as 'ArrayRef[HexNum]';

  subtype 'ArrayRefOfInts'
      => as 'ArrayRef[Int]';

  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 it will not
coerce a single hex number. To do that, we need to define a separate
coercion:

  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 explicit.

=head1 TYPE UNIONS

Moose allows you to say that an attribute can be of two or more
disparate types. For example, we might allow an C<Object> or
C<FileHandle>:

  has 'output' => (
      is  => 'rw',
      isa => 'Object | FileHandle',
  );

Moose actually parses that string and recognizes that you are creating
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 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') };

We can coerce file handles to an object that satisfies this condition
with a simple wrapper class:

  package FHWrapper;

  use Moose;

  has 'handle' => (
      is  => 'ro',
      isa => 'FileHandle',
  );

  sub print {
      my $self = shift;
      my $fh   = $self->handle();

      print $fh @_;
  }

Now we can define a coercion from C<FileHandle> to our wrapper class:

  coerce 'CanPrint'
      => from 'FileHandle'
      => via { FHWrapper->new( handle => $_ ) };

  has 'output' => (
      is     => 'rw',
      isa    => 'CanPrint',
      coerce => 1,
  );

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.

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 );

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:

  has 'size' => (
      is => 'rw',
      isa => subtype 'Int' => where { $_ > 0 },
  );

This is handy when you want to create a one-off type and don't want to
"pollute" the global namespace registry.

=head1 VALIDATING METHOD PARAMETERS

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 L<MooseX::Params::Validate>. This
lets you validate a set of named parameters using Moose types:

  use Moose;
  use MooseX::Params::Validate;

  sub foo {
      my $self   = shift;
      my %params = validated_hash(
          \@_,
          bar => { isa => 'Str', default => 'Moose' },
      );
      ...
  }

L<MooseX::Params::Validate> also supports coercions.

There are several more powerful extensions that support method
parameter validation using Moose types, including
L<MooseX::Method::Signatures>, which gives you a full-blown C<method>
keyword.

  method morning (Str $name) {
      $self->say("Good morning ${name}!");
  }

=head1 LOAD ORDER ISSUES

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.

We have several recommendations for ameliorating this problem. 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>:

  class_type('MyApp::User')
      unless find_type_constraint('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 2009 by Infinity Interactive, Inc.

L<http://www.iinteractive.com>

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut
