kind
Kind in Kind
Sometimes you'll see a funny little ^
in a method call:
say Mu.^name; # OUTPUT:
# Mu
This does not make for a name
call on Mu
. As is the case with !
and
private methods, the ^
is special and significant; like .=
, it sugars. This
makes for a name
call on the HOW
of Mu
with Mu
as its first argument:
say Mu.HOW.name: Mu; # OUTPUT:
# Mu
The name
metamethod has to come from somewhere. Provided we're working with
Rakudo, in this case, the HOW
of Mu
originates from the
Metamodel::ClassHOW
metaclass, which does the
Metamodel::Naming metarole.
Mu
's behaviour as a type originates from the state of its HOW
, which
carries a type of its own. This is not a true Raku type; it is implemented in
untyped nqp, as is the case with most of the Metamodel
package.
Oversimplifying typechecks like this internally is a valid strategy in my view. If a value's type is already inferrable from prior signatures, there's no need to keep checking it. The problem is we need to actually be able to make such a check to begin with in order to enforce type safety in the greater stratums of the MOP at its most external layer. We have a greater capacity to deal with this from the ecosystem, though we make a vow to Rakudo in doing so.
Consider a scenario where we want to check for a HOW that can make a
fully-featured package declarator, e.g. module
. module
is relatively
simplistic as far as a HOW
goes: it can carry a :name
, :ver
, :auth
, and
:api
, as well as a WHY
and WHO
:
#|[ A versioned module for the ecosystem. ]
module Eco:auth<zef:Kaiepi>:ver<0.0.1>:api<1> { }
This forwards a :$name
, :$ver
, :$auth
, and :$api
to the new_type
method on the HOW specified by the module
package declarator, which is
Metamodel::ModuleHOW
, which sets its WHO
to a fresh Stash
, WHY
being
set a little later. This information is all stored with API provided by
Metamodel::Naming
, Metamodel::Documenting
, Metaomdel::Versioning
, and
Metaomdel::Stashing
. If we want to check for a HOW that's compatible with
such a declarator, we could perhaps use a Junction
of these metaroles,
excluding the Metamodel::Stashing
that parametric roles lack:
say Mu.HOW ~~ Metamodel::Naming & Metamodel::Documenting & Metamodel::Versioning; # OUTPUT:
# Cannot find method 'find_method' on object of type NQPParametricRoleHOW
# in any at gen/moar/stage2/NQPCORE.setting line 527
# in block <unit> at kind.raku line 1
Or not. Rakudo's metaroles aren't actually the Mu
type expected of all
objects in Raku, and we're forwarding them to a core typecheck. These are nqp
parametric roles; they do not inherit, and do not pun, and thus don't carry
Mu
! While we can forward metaobjects like these around nqp-style with Mu
and liberal application of is raw
. Thus is the impotus for my Kind
class:
use Kind:api<2>;
say Mu ~~ Kind[Metamodel::Naming & Metamodel::Documenting & Metamodel::Versioning]; # OUTPUT:
# True
This is a parametric typechecker for HOW
s of metaobjects that can thread
junctions essentially.