Help language development. Donate to The Perl Foundation

Kind cpan:KAIEPI last updated on 2020-12-12

README.pod6
=begin pod

[![Build Status](https://travis-ci.com/Kaiepi/p6-Kind.svg?branch=master)](https://travis-ci.com/Kaiepi/p6-Kind)

=head1 NAME

Kind - Typechecking based on kinds

=head1 SYNOPSIS

=begin code :lang<raku>
use Kind;

my constant Class = Kind[Metamodel::ClassHOW];

proto sub is-class(Mu --> Bool:D)             {*}
multi sub is-class(Mu $ where Class --> True) { }
multi sub is-class(Mu --> False)              { }

say Str.&is-class;  # OUTPUT: True
say Blob.&is-class; # OUTPUT: False
=end code

=head1 DESCRIPTION

Kind is an uninstantiable parametric type that can be used to typecheck values
based off their kind. If parameterized, it may be used in a C<where> clause or
on the right-hand side of a smartmatch to typecheck a value's HOW against its
type parameter.

Kind is documented. You can view the documentation for it and its methods at
any time using C<WHY>.

For examples of how to use Kind with any of Rakudo's kinds, see C<t/01-kind.t>.

=head1 METAMETHODS

=head2 method parameterize

=for code :lang<raku>
method ^parameterize(Kind:U $this is raw, Mu \K --> Kind:U) { }

Mixes in C<kind> and C<ACCEPTS> methods. See below.

Some useful values with which to parameterize Kind are:

=item a metaclass or metarole

=for code :lang<raku>
# Smartmatches any class.
Kind[Metamodel::ClassHOW]

=item a junction of metaclasses or metaroles

=for code :lang<raku>
# Smartmatches any type that supports naming, versioning, and documenting.
Kind[Metamodel::Naming & Metamodel::Versioning & Metamodel::Documenting]

=item a block

=for code :lang<raku>
# Smartmatches any parametric type.
Kind[{ use nqp; nqp::hllbool(nqp::can($_, 'parameterize')) }]

=item a metaobject

=begin code :lang<raku>
# This class' metamethods ensure they can only be called with itself or its
# subclasses.
class Configurable {
    my Map:D %CONFIGURATIONS{ObjAt:D};

    method ^configure(Configurable:_ $this where Kind[self], %configuration --> Map:D) {
        %CONFIGURATIONS{$this.WHAT.WHICH} := %configuration.Map
    }
    method ^configuration(Configurable:_ $this where Kind[self] --> Map:D) {
        %CONFIGURATIONS{$this.WHAT.WHICH} // Map.new
    }
}
=end code

=head1 METHODS

=head2 method ACCEPTS

=for code :lang<raku>
method ACCEPTS(Kind:U: Mu $checker is raw) { }

Returns C<True> if the HOW of C<$checker> typechecks against C<Kind>'s type
parameter, otherwise returns C<False>.

If C<Kind>'s type parameter has an C<ACCEPTS> method, this will smartmatch the
HOW of C<$checker> against it; otherwise, C<Metamodel::Primitives.is_type> will
be called with C<$checker>'s HOW and it. Most of the time, the former will be
the case; the latter behaviour exists because it's not guaranteed C<K> will
actually have C<Mu>'s methods (this is case with Rakudo's metaroles).

=head2 method kind

=for code :lang<raku>
method kind(Kind:U: --> Mu) { }

Returns C<Kind>'s type parameter.

=head1 AUTHOR

Ben Davies (Kaiepi)

=head1 COPYRIGHT AND LICENSE

Copyright 2020 Ben Davies

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.

=end pod