-
Notifications
You must be signed in to change notification settings - Fork 0
/
README.pod6
104 lines (73 loc) · 3.56 KB
/
README.pod6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
=begin pod
[![Build Status](https://github.com/Kaiepi/ra-Kind-Subset-Parametric/actions/workflows/test.yml/badge.svg)](https://github.com/Kaiepi/ra-Kind-Subset-Parametric/actions/workflows/test.yml)
=head1 NAME
Kind::Subset::Parametric - Support for generic subsets
=head1 SYNOPSIS
=begin code :lang<raku>
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
}
=end code
=head1 DESCRIPTION
C<Kind::Subset::Parametric> enhances subsets with support for parameterization.
This allows you to write subsets with generic C<where> clauses.
C<Kind::Subset::Parametric> is documented. You can refer to the documentation
for its trait and C<MetamodelX::ParametricSubset> at any time using C<WHY>.
=head1 TRAITS
=head2 will parameterize
=for code :lang<raku>
multi sub trait_mod:<will>(Mu \T where Subset, &body_block, :parameterize($)!)
This trait mixes the C<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 C<&body_block>, which is
what makes it possible to parameterize the subset.
The main metamethod of interest this metarole provides is C<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 C<of>), and the return value of
the body block when invoked with the arguments as its refinement (the value of
C<where>).
For example, given an identity type:
=for code :lang<raku>
subset Identity will parameterize { $_ } where { !!! };
C<Identity[Any]> may be written to produce:
=for code :lang<raku>
subset ::('Identity[Any]') where Any;
Note the stubbed C<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 C<!!!> stub
will throw. Historically, C<...> was used, but failures don't necessarily sink
when the typechecker's nqp is involved.
The body block may be introspected with the C<body_block> metamethod, which
returns the body block it was parameterized with given a subset type.
C<set_body_block> must be called after being instantiated either by mixin on a
HOW or by C«&trait_mod:<does>» in order to replace this.
Refer to C<t/02-will.t> for more examples of how to use this trait.
=head1 AUTHOR
Ben Davies (Kaiepi)
=head1 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.
=end pod