--- /dev/null
+
+use MooseX::Types -declare [qw/Str/];
+use MooseX::Types::Faceted qw(Str);
+
+subtype Name()
+ => as Str()
+ => with hasMaxLength(25),
+ isWordCharacters(),
+ callBack {
+
+
+
+ => as Faceted[
+ Str(),
+ hasMaxLength(25),
+ ],
+
+
+use MooseX::Types::Moose qw(Int Str ArrayRef HashRef Object);
+use MooseX::Types::Structured qw(Dict);
+
+use MooseX::Types
+ -declare => [qw/PositiveInt Length/];
+
+use MooseX::Types::Parameterizable
+ -declare => [qw/MinLength MaxLength Size/];
+
+subtype PositiveInt,
+ as Int,
+ where { $_ >= 0 };
+
+type Length,
+ where { exists $_ && defined $_ };
+
+coerce Length,
+ from PositiveInt,
+ via { $_ },
+ from Str,
+ via { length $_ },
+ from ArrayRef,
+ via { scalar @$_ },
+ from HashRef,
+ via { scalar keys %$_ };
+
+subtype MinLength[Length],
+ as Value,
+ where {
+ my ($check, $parameter) = @_
+ return $parameter < length($check) ? 1:0;
+ };
+
+subtype MaxLength[Length],
+ as Value,
+ where {
+ my ($check, $parameter) = @_
+ return $parameter >= length($check) ? 1:0;
+ };
+
+subtype Size[Dict[max=>MaxLength,min=>MinLength]],
+ as Value,
+ where {
+ my ($check, $parameter) = @_;
+ $parameter->{max} > $parameter->{min};
+ }
+
+
+ Size[min=>5,max=>10]->check('aabbcc'); ## OK, length 6 in range
+ Size[min=>5,max=>10]->check('aa'); ## Not OK, length 2 out of range
+ Size[min=>5,max=>10]->check([1..8]); ## OK via coercion
+ Size[min=>1,max=>3]->check({a=>1,b=>2}); ## Ok via coercion
+ Size[min=>5,max=>10]->check($object); ## Not at least an Int
+
+ Size[min=>-10,max=>100]; ## NOT PositiveInt
+ Size[min=>'aaa', max=>100]; ## Not an Int
+ Size[min=>5, max=>2]; ## Not a Range
+
+
--- /dev/null
+
+## MyApp/Types.pm;
+
+ use MooseX::Declare::Types;
+ use MooseX::Types::Moose qw(Str Int);
+ use MooseX::Types::Structured qw(Dict Optional);
+
+ ## Possible interface for facets, with are a bit like roles for types. This
+ ## just a sketch, doesn't represent a lot of thought.
+ use MooseX::Types::Facets {
+ Str => [qw/ hasMinimumLength hasMaximumLength isWords matchesRegex/ ],
+ };
+
+ subtype FullName {
+ as Str;
+ having hasMinimumLength(2),
+ matchesPattern(
+ strategy=>Regexp,
+ pattern=>qr/
+ ^
+ \w{2,35}
+ \s
+ \w{0,25}
+ \s*
+ \w{2,50}
+ $
+ /x
+ );
+
+ parameter length => (
+ isa=>Int,
+ default=>100
+ );
+
+ parameterizes($p Parameters) {
+ having hasMaximumLength($p->length);
+ }
+ }
+
+ subtype Name {
+
+ parameter total_length => (
+ isa=>Int,
+ default=>60,
+ );
+
+ parameter part_max_lengths => (
+ isa=>Dict[
+ first=>Optional[Int],
+ middle=>Optional[Int],
+ last=>Optional[Int],
+ ],
+ );
+
+ my $Namepart = subtype {
+ as Str;
+ having isWords(maximum_words=>1),
+ hasMinimumLength(2);
+
+ parameter max_length => (
+ isa=>int,
+ default=>20
+ );
+
+ parameterize($p Parameters) {
+ having hasMaximumLength($p->max_length);
+ }
+ }
+
+ parameterize($p Parameters) {
+
+ as Dict[
+ first => $NamePart(
+ max_length=>$p->part_max_lengths->{first},
+ ),
+ middle => Optional[
+ $NamePart(
+ max_length=>$p->part_max_lengths->{middle}
+ ),
+ ],
+ last => $NamePart(
+ max_length=>$p->part_max_lengths->{last},
+ ),
+ ];
+
+ having hasMaximumLength($p->total_length);
+ }
+ }
+
+
+## MyApp/MyClass/Foo.pm
+
+ use MooseX::Declare;
+ use MooseX::Types qw(EmailAddress);
+ use MyApp::Types qw(FullName Name);
+
+ Class Foo {
+
+ with Class::DBIx::Role::Result => (
+ resultset_class => '',
+ fields => {
+ fullname => ...,
+ name => ...,
+ },
+ );
+
+ ## fullname would have a minimum of 2 characters, a maximum of 45 and
+ ## would be composed of a maximum of 3 words separated by whitespace
+
+ has fullname => (
+ is=>'rw',
+ isa=>FullName(length=>45),
+ );
+
+ ## name would be a HashRef with two required keys 'first' and 'last'
+ ## and a single optional key called 'middle'. each key value must be a
+ ## str composed of a single word with a minimum character length of 2
+ ## and maximum lengths of first=>35, middle=>25 and last=>50. Also the
+ ## overall total length.
+
+ has name => (
+ is=>'rw',
+ isa=>Name(
+ total_length=>95,
+ part_max_lengths=>{
+ first=>35,
+ middle=>25,
+ last=>50,
+ },
+ ),
+ );
+
+ method email($recipient Email) {
+ ....
+ }
+ }
+
+
+ use aliased MyApp::MyClass::Foo;
+
+ my $foo = Foo->new(
+ fullname=>'Vanessa Li',
+ name=>{
+ first=>'John',
+ middle=>'James',
+ last=>'Napiorkowski',
+ },
+ );
+
+ my $foo_set = Foo->search( name => sub { $self->search ... });
+
+
+ ## COERCSIONS
+
+
+coercion fixPerson($person Person) {
+ from Tuple($name Str, $age Int) {
+ $person->XXXXX(name=>$name, age=>$age);
+ }
+ from Dict(
+ :$fullname Fullname,
+ :$dob DateTime
+ ) {
+ my $name = "$fullname->{first} $fullname->{last}";
+ my $age = ($dob - DateTime-now)->years;
+ return $person->XXX(name=>$name, age=>$age);
+ }
+}
+
+
+has 'attribute' => (
+ is=>'rw',
+ isa=> Person->coercions(fixPerson, MorePeople),
+);
+
+
+
+subtype myDelegate,
+ as Delegate[Signature];
+
+
+type Signature,
+ as Optional[
+ Int,
+ Pairs[
+ Pair[name=>Int],
+ Pair[key=>Str],
+ ],
+
+
+
+
\ No newline at end of file