Add built local::lib
[catagits/Gitalist.git] / local-lib5 / man / man3 / MooseX::Types::Structured.3pm
diff --git a/local-lib5/man/man3/MooseX::Types::Structured.3pm b/local-lib5/man/man3/MooseX::Types::Structured.3pm
new file mode 100644 (file)
index 0000000..a5348d6
--- /dev/null
@@ -0,0 +1,915 @@
+.\" Automatically generated by Pod::Man 2.22 (Pod::Simple 3.10)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.ie \nF \{\
+.    de IX
+.    tm Index:\\$1\t\\n%\t"\\$2"
+..
+.    nr % 0
+.    rr F
+.\}
+.el \{\
+.    de IX
+..
+.\}
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "MooseX::Types::Structured 3"
+.TH MooseX::Types::Structured 3 "2010-03-26" "perl v5.8.8" "User Contributed Perl Documentation"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+MooseX::Types::Structured \- Structured Type Constraints for Moose
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+The following is example usage for this module.
+.PP
+.Vb 1
+\&    package Person;
+\&
+\&    use Moose;
+\&    use MooseX::Types::Moose qw(Str Int HashRef);
+\&    use MooseX::Types::Structured qw(Dict Tuple Optional);
+\&
+\&    ## A name has a first and last part, but middle names are not required
+\&    has name => (
+\&        isa=>Dict[
+\&            first => Str,
+\&            last => Str,
+\&            middle => Optional[Str],
+\&        ],
+\&    );
+\&
+\&    ## description is a string field followed by a HashRef of tagged data.
+\&    has description => (
+\&      isa=>Tuple[
+\&        Str,
+\&        Optional[HashRef],
+\&     ],
+\&    );
+\&
+\&        ## Remainder of your class attributes and methods
+.Ve
+.PP
+Then you can instantiate this class with something like:
+.PP
+.Vb 10
+\&    my $john = Person\->new(
+\&        name => {
+\&            first => \*(AqJohn\*(Aq,
+\&            middle => \*(AqJames\*(Aq
+\&            last => \*(AqNapiorkowski\*(Aq,
+\&        },
+\&        description => [
+\&            \*(AqA cool guy who loves Perl and Moose.\*(Aq, {
+\&                married_to => \*(AqVanessa Li\*(Aq,
+\&                born_in => \*(AqUSA\*(Aq,
+\&            };
+\&        ]
+\&    );
+.Ve
+.PP
+Or with:
+.PP
+.Vb 7
+\&    my $vanessa = Person\->new(
+\&        name => {
+\&            first => \*(AqVanessa\*(Aq,
+\&            last => \*(AqLi\*(Aq
+\&        },
+\&        description => [\*(AqA great student!\*(Aq],
+\&    );
+.Ve
+.PP
+But all of these would cause a constraint error for the 'name' attribute:
+.PP
+.Vb 2
+\&    ## Value for \*(Aqname\*(Aq not a HashRef
+\&    Person\->new( name => \*(AqJohn\*(Aq );
+\&
+\&    ## Value for \*(Aqname\*(Aq has incorrect hash key and missing required keys
+\&    Person\->new( name => {
+\&        first_name => \*(AqJohn\*(Aq
+\&    });
+\&
+\&    ## Also incorrect keys
+\&    Person\->new( name => {
+\&        first_name => \*(AqJohn\*(Aq,
+\&        age => 39,
+\&    });
+\&
+\&    ## key \*(Aqmiddle\*(Aq incorrect type, should be a Str not a ArrayRef
+\&    Person\->new( name => {
+\&        first => \*(AqVanessa\*(Aq,
+\&        middle => [1,2],
+\&        last => \*(AqLi\*(Aq,
+\&    });
+.Ve
+.PP
+And these would cause a constraint error for the 'description' attribute:
+.PP
+.Vb 2
+\&    ## Should be an ArrayRef
+\&    Person\->new( description => \*(AqHello I am a String\*(Aq );
+\&
+\&    ## First element must be a string not a HashRef.
+\&    Person\->new (description => [{
+\&        tag1 => \*(Aqvalue1\*(Aq,
+\&        tag2 => \*(Aqvalue2\*(Aq
+\&    }]);
+.Ve
+.PP
+Please see the test cases for more examples.
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+A structured type constraint is a standard container Moose type constraint,
+such as an ArrayRef or HashRef, which has been enhanced to allow you to
+explicitly name all the allowed type constraints inside the structure.  The
+generalized form is:
+.PP
+.Vb 1
+\&    TypeConstraint[@TypeParameters or %TypeParameters]
+.Ve
+.PP
+Where 'TypeParameters' is an array reference or hash references of
+Moose::Meta::TypeConstraint objects.
+.PP
+This type library enables structured type constraints. It is built on top of the
+MooseX::Types library system, so you should review the documentation for that
+if you are not familiar with it.
+.SS "Comparing Parameterized types to Structured types"
+.IX Subsection "Comparing Parameterized types to Structured types"
+Parameterized constraints are built into core Moose and you are probably already
+familiar with the type constraints 'HashRef' and 'ArrayRef'.  Structured types
+have similar functionality, so their syntax is likewise similar. For example,
+you could define a parameterized constraint like:
+.PP
+.Vb 2
+\&    subtype ArrayOfInts,
+\&     as ArrayRef[Int];
+.Ve
+.PP
+which would constrain a value to something like [1,2,3,...] and so on.  On the
+other hand, a structured type constraint explicitly names all it's allowed
+\&'internal' type parameter constraints.  For the example:
+.PP
+.Vb 2
+\&    subtype StringFollowedByInt,
+\&     as Tuple[Str,Int];
+.Ve
+.PP
+would constrain it's value to things like ['hello', 111] but ['hello', 'world']
+would fail, as well as ['hello', 111, 'world'] and so on.  Here's another
+example:
+.PP
+.Vb 1
+\&        package MyApp::Types;
+\&
+\&    use MooseX::Types \-declare [qw(StringIntOptionalHashRef)];
+\&    use MooseX::Types::Moose qw(Str Int);
+\&        use MooseX::Types::Structured qw(Tuple Optional);
+\&
+\&    subtype StringIntOptionalHashRef,
+\&     as Tuple[
+\&        Str, Int,
+\&        Optional[HashRef]
+\&     ];
+.Ve
+.PP
+This defines a type constraint that validates values like:
+.PP
+.Vb 2
+\&    [\*(AqHello\*(Aq, 100, {key1 => \*(Aqvalue1\*(Aq, key2 => \*(Aqvalue2\*(Aq}];
+\&    [\*(AqWorld\*(Aq, 200];
+.Ve
+.PP
+Notice that the last type constraint in the structure is optional.  This is
+enabled via the helper Optional type constraint, which is a variation of the
+core Moose type constraint 'Maybe'.  The main difference is that Optional type
+constraints are required to validate if they exist, while 'Maybe' permits
+undefined values.  So the following example would not validate:
+.PP
+.Vb 1
+\&    StringIntOptionalHashRef\->validate([\*(AqHello Undefined\*(Aq, 1000, undef]);
+.Ve
+.PP
+Please note the subtle difference between undefined and null.  If you wish to
+allow both null and undefined, you should use the core Moose 'Maybe' type
+constraint instead:
+.PP
+.Vb 1
+\&        package MyApp::Types;
+\&
+\&    use MooseX::Types \-declare [qw(StringIntMaybeHashRef)];
+\&    use MooseX::Types::Moose qw(Str Int Maybe);
+\&    use MooseX::Types::Structured qw(Tuple);
+\&
+\&    subtype StringIntMaybeHashRef,
+\&     as Tuple[
+\&        Str, Int, Maybe[HashRef]
+\&     ];
+.Ve
+.PP
+This would validate the following:
+.PP
+.Vb 3
+\&    [\*(AqHello\*(Aq, 100, {key1 => \*(Aqvalue1\*(Aq, key2 => \*(Aqvalue2\*(Aq}];
+\&    [\*(AqWorld\*(Aq, 200, undef];
+\&    [\*(AqWorld\*(Aq, 200];
+.Ve
+.PP
+Structured constraints are not limited to arrays.  You can define a structure
+against a HashRef with the 'Dict' type constaint as in this example:
+.PP
+.Vb 5
+\&    subtype FirstNameLastName,
+\&     as Dict[
+\&        firstname => Str,
+\&        lastname => Str,
+\&     ];
+.Ve
+.PP
+This would constrain a HashRef that validates something like:
+.PP
+.Vb 1
+\&    {firstname => \*(AqChristopher\*(Aq, lastname => \*(AqParsons\*(Aq};
+.Ve
+.PP
+but all the following would fail validation:
+.PP
+.Vb 2
+\&    ## Incorrect keys
+\&    {first => \*(AqChristopher\*(Aq, last => \*(AqParsons\*(Aq};
+\&
+\&    ## Too many keys
+\&    {firstname => \*(AqChristopher\*(Aq, lastname => \*(AqParsons\*(Aq, middlename => \*(AqAllen\*(Aq};
+\&
+\&    ## Not a HashRef
+\&    [\*(AqChristopher\*(Aq, \*(AqParsons\*(Aq];
+.Ve
+.PP
+These structures can be as simple or elaborate as you wish.  You can even
+combine various structured, parameterized and simple constraints all together:
+.PP
+.Vb 6
+\&    subtype Crazy,
+\&     as Tuple[
+\&        Int,
+\&        Dict[name=>Str, age=>Int],
+\&        ArrayRef[Int]
+\&     ];
+.Ve
+.PP
+Which would match:
+.PP
+.Vb 1
+\&        [1, {name=>\*(AqJohn\*(Aq, age=>25},[10,11,12]];
+.Ve
+.PP
+Please notice how the type parameters can be visually arranged to your liking
+and to improve the clarity of your meaning.  You don't need to run then
+altogether onto a single line.  Additionally, since the 'Dict' type constraint
+defines a hash constraint, the key order is not meaningful.  For example:
+.PP
+.Vb 6
+\&        subtype AnyKeyOrder,
+\&         as Dict[
+\&                key1=>Int,
+\&                key2=>Str,
+\&                key3=>Int,
+\&         ];
+.Ve
+.PP
+Would validate both:
+.PP
+.Vb 2
+\&        {key1 => 1, key2 => "Hi!", key3 => 2};
+\&        {key2 => "Hi!", key1 => 100, key3 => 300};
+.Ve
+.PP
+As you would expect, since underneath its just a plain old Perl hash at work.
+.SS "Alternatives"
+.IX Subsection "Alternatives"
+You should exercise some care as to whether or not your complex structured
+constraints would be better off contained by a real object as in the following
+example:
+.PP
+.Vb 2
+\&    package MyApp::MyStruct;
+\&    use Moose;
+\&
+\&    ## lazy way to make a bunch of attributes
+\&    has $_ for qw(full_name age_in_years);
+\&
+\&    package MyApp::MyClass;
+\&    use Moose;
+\&
+\&    has person => (isa => \*(AqMyApp::MyStruct\*(Aq);
+\&
+\&    my $instance = MyApp::MyClass\->new(
+\&        person=>MyApp::MyStruct\->new(
+\&            full_name => \*(AqJohn\*(Aq,
+\&            age_in_years => 39,
+\&        ),
+\&    );
+.Ve
+.PP
+This method may take some additional time to setup but will give you more
+flexibility.  However, structured constraints are highly compatible with this
+method, granting some interesting possibilities for coercion.  Try:
+.PP
+.Vb 1
+\&    package MyApp::MyClass;
+\&
+\&    use Moose;
+\&    use MyApp::MyStruct;
+\&
+\&    ## It\*(Aqs recommended your type declarations live in a separate class in order
+\&    ## to promote reusability and clarity.  Inlined here for brevity.
+\&
+\&    use MooseX::Types::DateTime qw(DateTime);
+\&    use MooseX::Types \-declare [qw(MyStruct)];
+\&    use MooseX::Types::Moose qw(Str Int);
+\&    use MooseX::Types::Structured qw(Dict);
+\&
+\&    ## Use class_type to create an ISA type constraint if your object doesn\*(Aqt
+\&    ## inherit from Moose::Object.
+\&    class_type \*(AqMyApp::MyStruct\*(Aq;
+\&
+\&    ## Just a shorter version really.
+\&    subtype MyStruct,
+\&     as \*(AqMyApp::MyStruct\*(Aq;
+\&
+\&    ## Add the coercions.
+\&    coerce MyStruct,
+\&     from Dict[
+\&        full_name=>Str,
+\&        age_in_years=>Int
+\&     ], via {
+\&        MyApp::MyStruct\->new(%$_);
+\&     },
+\&     from Dict[
+\&        lastname=>Str,
+\&        firstname=>Str,
+\&        dob=>DateTime
+\&     ], via {
+\&        my $name = $_\->{firstname} .\*(Aq \*(Aq. $_\->{lastname};
+\&        my $age = DateTime\->now \- $_\->{dob};
+\&
+\&        MyApp::MyStruct\->new(
+\&            full_name=>$name,
+\&            age_in_years=>$age\->years,
+\&        );
+\&     };
+\&
+\&    has person => (isa=>MyStruct);
+.Ve
+.PP
+This would allow you to instantiate with something like:
+.PP
+.Vb 4
+\&    my $obj = MyApp::MyClass\->new( person => {
+\&        full_name=>\*(AqJohn Napiorkowski\*(Aq,
+\&        age_in_years=>39,
+\&    });
+.Ve
+.PP
+Or even:
+.PP
+.Vb 5
+\&    my $obj = MyApp::MyClass\->new( person => {
+\&        lastname=>\*(AqJohn\*(Aq,
+\&        firstname=>\*(AqNapiorkowski\*(Aq,
+\&        dob=>DateTime\->new(year=>1969),
+\&    });
+.Ve
+.PP
+If you are not familiar with how coercions work, check out the Moose cookbook
+entry Moose::Cookbook::Recipe5 for an explanation.  The section \*(L"Coercions\*(R"
+has additional examples and discussion.
+.SS "Subtyping a Structured type constraint"
+.IX Subsection "Subtyping a Structured type constraint"
+You need to exercise some care when you try to subtype a structured type as in
+this example:
+.PP
+.Vb 2
+\&    subtype Person,
+\&     as Dict[name => Str];
+\&
+\&    subtype FriendlyPerson,
+\&     as Person[
+\&        name => Str,
+\&        total_friends => Int,
+\&     ];
+.Ve
+.PP
+This will actually work \s-1BUT\s0 you have to take care that the subtype has a
+structure that does not contradict the structure of it's parent.  For now the
+above works, but I will clarify the syntax for this at a future point, so
+it's recommended to avoid (should not really be needed so much anyway).  For
+now this is supported in an \s-1EXPERIMENTAL\s0 way.  Your thoughts, test cases and
+patches are welcomed for discussion.  If you find a good use for this, please
+let me know.
+.SS "Coercions"
+.IX Subsection "Coercions"
+Coercions currently work for 'one level' deep.  That is you can do:
+.PP
+.Vb 5
+\&    subtype Person,
+\&     as Dict[
+\&        name => Str,
+\&        age => Int
+\&    ];
+\&
+\&    subtype Fullname,
+\&     as Dict[
+\&        first => Str,
+\&        last => Str
+\&     ];
+\&
+\&    coerce Person,
+\&     ## Coerce an object of a particular class
+\&     from BlessedPersonObject, via {
+\&        +{
+\&            name=>$_\->name,
+\&            age=>$_\->age,
+\&        };
+\&     },
+\&
+\&     ## Coerce from [$name, $age]
+\&     from ArrayRef, via {
+\&        +{
+\&            name=>$_\->[0],
+\&            age=>$_\->[1],
+\&        },
+\&     },
+\&     ## Coerce from {fullname=>{first=>...,last=>...}, dob=>$DateTimeObject}
+\&     from Dict[fullname=>Fullname, dob=>DateTime], via {
+\&        my $age = $_\->dob \- DateTime\->now;
+\&        my $firstn = $_\->{fullname}\->{first};
+\&        my $lastn = $_\->{fullname}\->{last}
+\&        +{
+\&            name => $_\->{fullname}\->{first} .\*(Aq \*(Aq. ,
+\&            age =>$age\->years
+\&        }
+\&     };
+.Ve
+.PP
+And that should just work as expected.  However, if there are any 'inner'
+coercions, such as a coercion on 'Fullname' or on 'DateTime', that coercion
+won't currently get activated.
+.PP
+Please see the test '07\-coerce.t' for a more detailed example.  Discussion on
+extending coercions to support this welcome on the Moose development channel or
+mailing list.
+.SS "Recursion"
+.IX Subsection "Recursion"
+Newer versions of MooseX::Types support recursive type constraints.  That is
+you can include a type constraint as a contained type constraint of itself.  For
+example:
+.PP
+.Vb 7
+\&        subtype Person,
+\&         as Dict[
+\&                name=>Str,
+\&                friends=>Optional[
+\&                        ArrayRef[Person]
+\&                ],
+\&         ];
+.Ve
+.PP
+This would declare a Person subtype that contains a name and an optional
+ArrayRef of Persons who are friends as in:
+.PP
+.Vb 10
+\&        {
+\&                name => \*(AqMike\*(Aq,
+\&                friends => [
+\&                        { name => \*(AqJohn\*(Aq },
+\&                        { name => \*(AqVincent\*(Aq },
+\&                        {
+\&                                name => \*(AqTracey\*(Aq,
+\&                                friends => [
+\&                                        { name => \*(AqStephenie\*(Aq },
+\&                                        { name => \*(AqIlya\*(Aq },
+\&                                ],
+\&                        },
+\&                ],
+\&        };
+.Ve
+.PP
+Please take care to make sure the recursion node is either Optional, or declare
+a Union with an non recursive option such as:
+.PP
+.Vb 5
+\&        subtype Value
+\&         as Tuple[
+\&                Str,
+\&                Str|Tuple,
+\&         ];
+.Ve
+.PP
+Which validates:
+.PP
+.Vb 10
+\&        [
+\&                \*(AqHello\*(Aq, [
+\&                        \*(AqWorld\*(Aq, [
+\&                                \*(AqIs\*(Aq, [
+\&                                        \*(AqGetting\*(Aq,
+\&                                        \*(AqOld\*(Aq,
+\&                                ],
+\&                        ],
+\&                ],
+\&        ];
+.Ve
+.PP
+Otherwise you will define a subtype thatis impossible to validate since it is
+infinitely recursive.  For more information about defining recursive types,
+please see the documentation in MooseX::Types and the test cases.
+.SH "TYPE CONSTRAINTS"
+.IX Header "TYPE CONSTRAINTS"
+This type library defines the following constraints.
+.SS "Tuple[@constraints]"
+.IX Subsection "Tuple[@constraints]"
+This defines an ArrayRef based constraint which allows you to validate a specific
+list of contained constraints.  For example:
+.PP
+.Vb 2
+\&    Tuple[Int,Str]; ## Validates [1,\*(Aqhello\*(Aq]
+\&    Tuple[Str|Object, Int]; ## Validates [\*(Aqhello\*(Aq, 1] or [$object, 2]
+.Ve
+.PP
+The Values of \f(CW@constraints\fR should ideally be MooseX::Types declared type
+constraints.  We do support 'old style' Moose string based constraints to a
+limited degree but these string type constraints are considered deprecated.
+There will be limited support for bugs resulting from mixing string and
+MooseX::Types in your structures.  If you encounter such a bug and really
+need it fixed, we will required a detailed test case at the minimum.
+.SS "Dict[%constraints]"
+.IX Subsection "Dict[%constraints]"
+This defines a HashRef based constraint which allowed you to validate a specific
+hashref.  For example:
+.PP
+.Vb 1
+\&    Dict[name=>Str, age=>Int]; ## Validates {name=>\*(AqJohn\*(Aq, age=>39}
+.Ve
+.PP
+The keys in \f(CW%constraints\fR follow the same rules as \f(CW@constraints\fR in the above
+section.
+.ie n .SS "Map[ $key_constraint, $value_constraint ]"
+.el .SS "Map[ \f(CW$key_constraint\fP, \f(CW$value_constraint\fP ]"
+.IX Subsection "Map[ $key_constraint, $value_constraint ]"
+This defines a HashRef based constraint in which both the keys and values are
+required to meet certain constraints.  For example, to map hostnames to \s-1IP\s0
+addresses, you might say:
+.PP
+.Vb 1
+\&  Map[ HostName, IPAddress ]
+.Ve
+.PP
+The type constraint would only be met if every key was a valid HostName and
+every value was a valid IPAddress.
+.SS "Optional[$constraint]"
+.IX Subsection "Optional[$constraint]"
+This is primarily a helper constraint for Dict and Tuple type constraints.  What
+this allows is for you to assert that a given type constraint is allowed to be
+null (but \s-1NOT\s0 undefined).  If the value is null, then the type constraint passes
+but if the value is defined it must validate against the type constraint.  This
+makes it easy to make a Dict where one or more of the keys doesn't have to exist
+or a tuple where some of the values are not required.  For example:
+.PP
+.Vb 5
+\&    subtype Name() => as Dict[
+\&        first=>Str,
+\&        last=>Str,
+\&        middle=>Optional[Str],
+\&    ];
+.Ve
+.PP
+Creates a constraint that validates against a hashref with the keys 'first' and
+\&'last' being strings and required while an optional key 'middle' is must be a
+string if it appears but doesn't have to appear.  So in this case both the
+following are valid:
+.PP
+.Vb 2
+\&    {first=>\*(AqJohn\*(Aq, middle=>\*(AqJames\*(Aq, last=>\*(AqNapiorkowski\*(Aq}
+\&    {first=>\*(AqVanessa\*(Aq, last=>\*(AqLi\*(Aq}
+.Ve
+.PP
+If you use the 'Maybe' type constraint instead, your values will also validate
+against 'undef', which may be incorrect for you.
+.SH "EXPORTABLE SUBROUTINES"
+.IX Header "EXPORTABLE SUBROUTINES"
+This type library makes available for export the following subroutines
+.SS "slurpy"
+.IX Subsection "slurpy"
+Structured type constraints by their nature are closed; that is validation will
+depend on an exact match between your structure definition and the arguments to
+be checked.  Sometimes you might wish for a slightly looser amount of validation.
+For example, you may wish to validate the first 3 elements of an array reference
+and allow for an arbitrary number of additional elements.  At first thought you
+might think you could do it this way:
+.PP
+.Vb 8
+\&    #  I want to validate stuff like: [1,"hello", $obj, 2,3,4,5,6,...]
+\&    subtype AllowTailingArgs,
+\&     as Tuple[
+\&       Int,
+\&       Str,
+\&       Object,
+\&       ArrayRef[Int],
+\&     ];
+.Ve
+.PP
+However what this will actually validate are structures like this:
+.PP
+.Vb 1
+\&    [10,"Hello", $obj, [11,12,13,...] ]; # Notice element 4 is an ArrayRef
+.Ve
+.PP
+In order to allow structured validation of, \*(L"and then some\*(R", arguments, you can
+use the \*(L"slurpy\*(R" method against a type constraint.  For example:
+.PP
+.Vb 1
+\&    use MooseX::Types::Structured qw(Tuple slurpy);
+\&
+\&    subtype AllowTailingArgs,
+\&     as Tuple[
+\&       Int,
+\&       Str,
+\&       Object,
+\&       slurpy ArrayRef[Int],
+\&     ];
+.Ve
+.PP
+This will now work as expected, validating ArrayRef structures such as:
+.PP
+.Vb 1
+\&    [1,"hello", $obj, 2,3,4,5,6,...]
+.Ve
+.PP
+A few caveats apply.  First, the slurpy type constraint must be the last one in
+the list of type constraint parameters.  Second, the parent type of the slurpy
+type constraint must match that of the containing type constraint.  That means
+that a Tuple can allow a slurpy ArrayRef (or children of ArrayRefs, including
+another Tuple) and a Dict can allow a slurpy HashRef (or children/subtypes of
+HashRef, also including other Dict constraints).
+.PP
+Please note the the technical way this works 'under the hood' is that the
+slurpy keyword transforms the target type constraint into a coderef.  Please do
+not try to create your own custom coderefs; always use the slurpy method.  The
+underlying technology may change in the future but the slurpy keyword will be
+supported.
+.SH "ERROR MESSAGES"
+.IX Header "ERROR MESSAGES"
+Error reporting has been improved to return more useful debugging messages. Now
+I will stringify the incoming check value with Devel::PartialDump so that you
+can see the actual structure that is tripping up validation.  Also, I report the
+\&'internal' validation error, so that if a particular element inside the
+Structured Type is failing validation, you will see that.  There's a limit to
+how deep this internal reporting goes, but you shouldn't see any of the \*(L"failed
+with \s-1ARRAY\s0(\s-1XXXXXX\s0)\*(R" that we got with earlier versions of this module.
+.PP
+This support is continuing to expand, so it's best to use these messages for
+debugging purposes and not for creating messages that 'escape into the wild'
+such as error messages sent to the user.
+.PP
+Please see the test '12\-error.t' for a more lengthy example.  Your thoughts and
+preferable tests or code patches very welcome!
+.SH "EXAMPLES"
+.IX Header "EXAMPLES"
+Here are some additional example usage for structured types.  All examples can
+be found also in the 't/examples.t' test.  Your contributions are also welcomed.
+.SS "Normalize a HashRef"
+.IX Subsection "Normalize a HashRef"
+You need a hashref to conform to a canonical structure but are required accept a
+bunch of different incoming structures.  You can normalize using the Dict type
+constraint and coercions.  This example also shows structured types mixed which
+other MooseX::Types libraries.
+.PP
+.Vb 1
+\&    package Test::MooseX::Meta::TypeConstraint::Structured::Examples::Normalize;
+\&
+\&    use Moose;
+\&    use DateTime;
+\&
+\&    use MooseX::Types::Structured qw(Dict Tuple);
+\&    use MooseX::Types::DateTime qw(DateTime);
+\&    use MooseX::Types::Moose qw(Int Str Object);
+\&    use MooseX::Types \-declare => [qw(Name Age Person)];
+\&
+\&    subtype Person,
+\&     as Dict[
+\&        name=>Str,
+\&        age=>Int,
+\&     ];
+\&
+\&    coerce Person,
+\&     from Dict[
+\&        first=>Str,
+\&        last=>Str,
+\&        years=>Int,
+\&     ], via { +{
+\&        name => "$_\->{first} $_\->{last}",
+\&        age => $_\->{years},
+\&     }},
+\&     from Dict[
+\&        fullname=>Dict[
+\&                last=>Str,
+\&                first=>Str,
+\&        ],
+\&        dob=>DateTime,
+\&     ],
+\&     ## DateTime needs to be inside of single quotes here to disambiguate the
+\&     ## class package from the DataTime type constraint imported via the
+\&     ## line "use MooseX::Types::DateTime qw(DateTime);"
+\&     via { +{
+\&        name => "$_\->{fullname}{first} $_\->{fullname}{last}",
+\&        age => ($_\->{dob} \- \*(AqDateTime\*(Aq\->now)\->years,
+\&     }};
+\&
+\&    has person => (is=>\*(Aqrw\*(Aq, isa=>Person, coerce=>1);
+.Ve
+.PP
+And now you can instantiate with all the following:
+.PP
+.Vb 6
+\&    _\|_PACKAGE_\|_\->new(
+\&        person=>{
+\&            name=>\*(AqJohn Napiorkowski\*(Aq,
+\&            age=>39,
+\&        },
+\&    );
+\&
+\&    _\|_PACKAGE_\|_\->new(
+\&        person=>{
+\&            first=>\*(AqJohn\*(Aq,
+\&            last=>\*(AqNapiorkowski\*(Aq,
+\&            years=>39,
+\&        },
+\&    );
+\&
+\&    _\|_PACKAGE_\|_\->new(
+\&        person=>{
+\&            fullname => {
+\&                first=>\*(AqJohn\*(Aq,
+\&                last=>\*(AqNapiorkowski\*(Aq
+\&            },
+\&            dob => \*(AqDateTime\*(Aq\->new(
+\&                year=>1969,
+\&                month=>2,
+\&                day=>13
+\&            ),
+\&        },
+\&    );
+.Ve
+.PP
+This technique is a way to support various ways to instantiate your class in a
+clean and declarative way.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+The following modules or resources may be of interest.
+.PP
+Moose, MooseX::Types, Moose::Meta::TypeConstraint,
+MooseX::Meta::TypeConstraint::Structured
+.SH "TODO"
+.IX Header "TODO"
+Here's a list of stuff I would be happy to get volunteers helping with:
+.PP
+.Vb 4
+\&        * All POD examples need test cases in t/documentation/*.t
+\&        * Want to break out the examples section to a separate cookbook style POD.
+\&        * Want more examples and best practice / usage guidance for authors
+\&        * Need to clarify deep coercions,
+.Ve
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+John Napiorkowski <jjnapiork@cpan.org>
+.SH "CONTRIBUTORS"
+.IX Header "CONTRIBUTORS"
+The following people have contributed to this module and agree with the listed
+Copyright & license information included below:
+.PP
+.Vb 3
+\&    Florian Ragwitz, <rafl@debian.org>
+\&    Yuval Kogman, <nothingmuch@woobling.org>
+\&    Tomas Doran, <bobtfish@bobtfish.net>
+.Ve
+.SH "COPYRIGHT & LICENSE"
+.IX Header "COPYRIGHT & LICENSE"
+Copyright 2008\-2009, John Napiorkowski <jjnapiork@cpan.org>
+.PP
+This program is free software; you can redistribute it and/or modify it under
+the same terms as Perl itself.