txt: ## dist_zef-Kaiepi-Kind.md
  [![Build Status](https://github.com/Kaiepi/ra-Kind/actions/workflows/test.yaml/badge.svg)](https://github.com/Kaiepi/ra-Kind/actions/workflows/test.yaml)
  
  # NAME
  
  Kind - Typechecking based on kinds
  
  # SYNOPSIS
  
  ```
  use Kind;
  
  my constant Class = Kind[Metamodel::ClassHOW];
  
  proto sub is-class(Mu --> Bool:D)  {*}
  multi sub is-class(Class --> True) { }
  multi sub is-class(Mu --> False)   { }
  
  say Str.&is-class;  # OUTPUT: True
  say Blob.&is-class; # OUTPUT: False
  
  ```
  
  # DESCRIPTION
  
  `Kind` is an uninstantiable parametric type that can be used to typecheck values based off their kind. A parameterization produces a type object that can process the HOW of a type in a typecheck context with `ACCEPTS` when available, otherwise falling back to the bare typecheck.
  
  `Kind` is documented. You can view the documentation for it and its methods at any time using `WHY`.
  
  # METAMETHODS
  
  ## method parameterize
  
  ```
  method ^parameterize(|args) is raw
  
  ```
  
  Produces a parameterization by delegating to `^kind` with `args`.
  
  ## method kind
  
  ```
  method ^kind(Mu $obj is raw, Mu \K, Mu:U \T = Mu) is raw
  
  ```
  
  Produces a cached subset with a refinement (`where`) built from `K` and a refinement (`of`) from `T` if present. This backs `^parameterize` so as to allow for a different parameterizer in a subtype. This is more or less a wrapper for `Metamodel::Primitives.parameterize_type`.
  
  Some useful values with which to produce a type are:
  
  * a metaclass or metarole
  
  ```
  # Smartmatches any class.
  Kind[Metamodel::ClassHOW]
  
  ```
  
  * a junction of metaclasses or metaroles
  
  ```
  # Smartmatches any type that supports naming, versioning, and documenting.
  Kind[Metamodel::Naming & Metamodel::Versioning & Metamodel::Documenting]
  
  ```
  
  * a block
  
  ```
  # Smartmatches any parametric type.
  Kind[{ use nqp; nqp::hllbool(nqp::can($_, 'parameterize')) }]
  
  ```
  
  * a metaobject
  
  ```
  # This class' metamethods constrain their metaobject to itself or its subtypes.
  class Configurable {
      my constant K := Kind[$?CLASS.HOW.WHAT, $?CLASS];
  
      my constant %configuration := hash;
  
      method ^configure(K $obj, %config --> Map:D) {
          %configuration{$obj.WHAT.WHICH} := %config.Map
      }
  
      method ^configuration(K $obj --> Map:D) {
          %configuration{$obj.WHAT.WHICH} // Map.new
      }
  }
  
  ```
  
  For more examples of parameterizations of `Kind`, refer to `t/01-typecheck.t`.
  
  # SYMBOLS
  
  ## &set\_parameterizer
  
  ```
  our sub set_parameterizer(Mu $obj is raw, &parameterizer = &parameterize --> Nil)
  
  ```
  
  Applies the parameterizer of `Kind` to a metaobject, providing it with a parameterization cache. A subtype needs to apply this at `BEGIN`-time in order to parameterize with the default metamethods, for instance:
  
  ```
  class Kind::Instantiable is Kind {
      BEGIN Kind::set_parameterizer($?CLASS);
  }
  
  ```
  
  A `&parameterizer` may be provided, in which case that will be set instead. This should carry a compatible signature with `&parameterize`.
  
  For more examples of how to subclass `Kind`, refer to `t/02-meta.t`.
  
  ## &parameterize
  
  ```
  our sub parameterize(Mu $root is raw, Any $args) is raw
  
  ```
  
  Given the `$root` metaobject of the parameterization and its `$args`, produces a type object minus the caching. `$args` is assumed to carry `K` at position `0` and `T`, if present, at position `1`.
  
  # AUTHOR
  
  Ben Davies (Kaiepi)
  
  # COPYRIGHT AND LICENSE
  
  Copyright 2022 Ben Davies
  
  This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.
  