Help language development. Donate to The Perl Foundation

ad22a7ac7c91e2ce21fec0267f0e4f6c28446054/

Kind::Subset::Parametric - Support for generic subsets

use Kind::Subset::Parametric; # Arrays don't type their elements by default: my @untyped = 1, 2, 3; say @untyped.^name; # OUTPUT: Array # You can make it so they do by parameterizing Array: my Int:D @typed = 1, 2, 3; say @typed.^name; # OUTPUT: Array[Int:D] # But you can't typecheck untyped arrays using these parameterizations: say @typed ~~ Array[Int:D]; # OUTPUT: True say @untyped ~~ Array[Int:D]; # OUTPUT: False # So let's make our own array type that handles this using a parametric subset: subset TypedArray of Array will parameterize -> ::T { proto sub check(Array) {*} multi sub check(Array[T] --> True) { } multi sub check(Array:U --> False) { } multi sub check(Array:D $topic) { so $topic.all ~~ T } &check } where { !!! }; # Now they can both be typechecked: given TypedArray[Int:D] -> IntArray { say @typed ~~ IntArray; # OUTPUT: True say @untyped ~~ IntArray; # OUTPUT: True say <foo bar baz> ~~ IntArray; # OUTPUT: False }

`Kind::Subset::Parametric`

enhances subsets with support for parameterization. This allows you to write subsets with generic `where`

clauses.

`Kind::Subset::Parametric`

is documented. You can refer to the documentation for its trait and `MetamodelX::ParametricSubset`

at any time using `WHY`

.

multi sub trait_mod:<will>(Mu \T where Subset, &body_block, :parameterize($)!)

This trait mixes the `MetamodelX::ParametricSubset`

metarole into the HOW of the type it is applied to, which may only be a subset of some sort. Afterwards, the subset will be instantiated with its `&body_block`

, which is what makes it possible to parameterize the subset.

The main metamethod of interest this metarole provides is `parameterize`

, which accepts arbitrary type argumentss. This is created using a name (generated similarly to how the name of a parametric role is generated), the refinee of the parametric subset (the value of `of`

), and the return value of the body block when invoked with the arguments as its refinement (the value of `where`

).

For example, given an identity type:

subset Identity will parameterize { $_ } where { !!! };

`Identity[Any]`

may be written to produce:

subset ::('Identity[Any]') where Any;

Note the stubbed `where`

clause. Parametric subsets can still be given a refinement when this trait is applied, which handles typechecking against the subset when it has not been parameterized. If it's not desirable for a parametric subset to typecheck without being parameterized, the `!!!`

stub will throw. Historically, `...`

was used, but failures don't necessarily sink when the typechecker's nqp is involved.

The body block may be introspected with the `body_block`

metamethod, which returns the body block it was parameterized with given a subset type. `set_body_block`

must be called after being instantiated either by mixin on a HOW or by `&trait_mod:<does>`

in order to replace this.

Refer to `t/02-will.t`

for more examples of how to use this trait.

Ben Davies (Kaiepi)

Copyright 2022 Ben Davies

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