### ----------------------------------------------------
### -- AI::FANN
### -- Licenses: Artistic-2.0
### -- Authors: Jonathan Scott Duff <duff@pobox.com>, José Joaquín Atria <jjatria@cpan.org>
### -- File: README.md
### ----------------------------------------------------
### -- Chunk 2 of 2
 If called with a positional
argument, it will be coerced to a [Num] and set as the new weight decay shift.

The default value is -6.644.

### sarprop-error-threshold

``` raku
multi method sarprop-error-threshold returns Num

multi method sarprop-error-threshold (
    Num() $value,
) returns self
```

If called with no positional arguments, this method returns the current error
threshold factor used during SARPROP training. If called with a positional
argument, it will be coerced to a [Num] and set as the new error threshold
factor.

The default value is 0.1.

### sarprop-step-error-shift

``` raku
multi method sarprop-step-error-shift returns Num

multi method sarprop-step-error-shift (
    Num() $value,
) returns self
```

If called with no positional arguments, this method returns the current step
error shift used during SARPROP training. If called with a positional
argument, it will be coerced to a [Num] and set as the new step error shift.

The default value is 1.385.

### sarprop-temperature

``` raku
multi method sarprop-temperature returns Num

multi method sarprop-temperature (
    Num() $value,
) returns self
```

If called with no positional arguments, this method returns the current decay
shift used during SARPROP training. If called with a positional argument, it
will be coerced to a [Num] and set as the new decay shift.

The default value is 0.015.

## Cascade Training

Cascade training differs from ordinary training in that it starts with an
empty neural network and then adds neurons one by one, while it trains the
neural network. The main benefit of this approach is that you do not have to
guess the number of hidden layers and neurons prior to training, but cascade
training has also proved better at solving some problems.

The basic idea of cascade training is that a number of candidate neurons are
trained separate from the real network, then the most promising of these
candidate neurons is inserted into the neural network. Then the output
connections are trained and new candidate neurons are prepared. The candidate
neurons are created as shortcut connected neurons in a new hidden layer, which
means that the final neural network will consist of a number of hidden layers
with one shortcut connected neuron in each.

For methods supporting ordinary, or fixed topology training, see the
[Training](#training) section above.

### cascade-train

``` raku
# fann_cascadetrain_on_data
multi method cascade-train (
    AI::FANN::TrainData:D $data,
    Int() :$max-neurons!,
    Int() :$neurons-between-reports!,
    Num() :$desired-error!,
) returns self

# fann_cascadetrain_on_file
multi method cascade-train (
    IO() $path,
    Int() :$max-neurons!,
    Int() :$neurons-between-reports!,
    Num() :$desired-error!,
) returns self
```

Trains the network on an entire dataset for a period of time using the
Cascade2 training algorithm. The dataset can be passed as an
AI::FANN::TrainData object in the `data` parameter. Alternatively, if
the `path` is set, it will be coerced to an [IO::Path] object and the
training data will be read from there instead.

This algorithm adds neurons to the neural network while training, which means
that it needs to start with an ANN without any hidden layers. The neural
network should also use shortcut connections, so the `shortcut` flag should
be used when invoking [new](#new), like this

``` raku
my $ann = AI::FANN.new: :shortcut,
    layers => [ $data.num-input, $data.num-output ];
```

### cascade-num-candidates

``` raku
# fann_get_cascade_num_candidates
multi method cascade-num-candidates returns Int
```

Returns the number of candidates used during training.

The number of candidates is calculated by multiplying the value returned by
[cascade-activation-functions-count](#cascade-activation-functions-count),
[cascade-activation-steepnesses-count](#cascade-activation-steepnesses-count),
and [cascade-num-candidate-groups](#cascade-num-candidate-groups).

The actual candidates is defined by the
[cascade-activation-functions](#cascade-activation-functions) and
[cascade-activation-steepnesses](#cascade-activation-steepnesses) arrays.
These arrays define the activation functions and activation steepnesses used
for the candidate neurons. If there are 2 activation functions in the
activation function array and 3 steepnesses in the steepness array, then there
will be 2x3=6 different candidates which will be trained. These 6 different
candidates can be copied into several candidate groups, where the only
difference between these groups is the initial weights. If the number of
groups is set to 2, then the number of candidate neurons will be 2x3x2=12.
The number of candidate groups can be set with
[cascade-num-candidate-groups](#cascade-num-candidate-groups).

The default number of candidates is 6x4x2 = 48

### cascade-num-candidate-groups

``` raku
# fann_get_cascade_num_candidate_groups
multi method cascade-num-candidate-groups returns Int

# fann_set_cascade_num_candidate_groups
multi method cascade-num-candidate-groups ( Int $groups ) returns self
```

If called with no positional arguments, this method returns the number of
candidate groups used during training. If called with an Int as a positional
argument, it will be set as the new value.

The number of candidate groups is the number of groups of identical candidates
which will be used during training.

This number can be used to have more candidates without having to define new
parameters for the candidates.

See [cascade-num-candidates](#cascade-num-candidates) for a description of
which candidate neurons will be generated by this parameter.

The default number of candidate groups is 2

### cascade-candidate-limit

``` raku
# fann_get_cascade_candidate_limit
multi method cascade-candidate-limit returns Num

# fann_set_cascade_candidate_limit
multi method cascade-candidate-limit ( Num() $value ) returns self
```

The candidate limit is a limit for how much the candidate neuron may be
trained. It limits the proportion between the MSE and candidate score. Set
this to a lower value to avoid overfitting and to a higher if overfitting is
not a problem.

If called with no positional arguments, this method returns the current
candidate limit. If called with a positional argument, it will be coerced
to a [Num] and set as the new candidate limit.

The default candidate limit is 1000.

### cascade-weight-multiplier

``` raku
# fann_get_cascade_weight_multiplier
multi method cascade-weight-multiplier returns Num

# fann_set_cascade_weight_multiplier
multi method cascade-weight-multiplier ( Num() $value ) returns self
```

The weight multiplier is a parameter which is used to multiply the weights
from the candidate neuron before adding the neuron to the neural network.
This parameter is usually between 0 and 1, and is used to make the training a
bit less aggressive.

If called with no positional arguments, this method returns the current
weight multiplier. If called with a positional argument, it will be coerced
to a [Num] and set as the new weight multiplier.

The default weight multiplier is 0.4

### cascade-output-change-fraction

``` raku
# fann_get_cascade_output_change_fraction
multi method cascade-output-change-fraction returns Num

# fann_set_cascade_output_change_fraction
multi method cascade-output-change-fraction ( Num() $value ) returns self
```

The cascade output change fraction is a number between 0 and 1 determining how
large a fraction the [mean-square-error](#mean-square-error) should change
within [cascade-output-stagnation-epochs](#cascade-output-stagnation-epochs)
during training of the output connections, in order for the training not to
stagnate. If the training stagnates, the training of the output connections
will be ended and new candidates will be prepared.

If the MSE does not change by a fraction of the value returned by this method
during a period of
[cascade-output-stagnation-epochs](#cascade-output-stagnation-epochs), the
training of the output connections is stopped because the training has stagnated.

If the cascade output change fraction is low, the output connections will be
trained more and if the fraction is high they will be trained less.

If called with no positional arguments, this method returns the current
output change fraction. If called with a positional argument, it will be
coerced to a [Num] and set as the new fraction.

The default cascade output change fraction is 0.01, which is equivalent to a
1% change in MSE.

### cascade-candidate-change-fraction

``` raku
# fann_get_cascade_candidate_change_fraction
multi method cascade-candidate-change-fraction returns Num

# fann_set_cascade_candidate_change_fraction
multi method cascade-candidate-change-fraction ( Num() $value ) returns self
```

The cascade candidate change fraction is a number between 0 and 1 determining
how large a fraction the [mean-square-error](#mean-square-error) should change
within [cascade-output-stagnation-epochs](#cascade-output-stagnation-epochs)
during training of the candidate neurons, in order for the training not to
stagnate. If the training stagnates, the training of candidate neurons will be
ended and the best candidate will be selected.

If the MSE does not change by a fraction of the value returned by this method
during a period of
[cascade-candidate-stagnation-epochs](#cascade-candidate-stagnation-epochs), the
training of the candidate neurons is stopped because the training has stagnated.

If the cascade candidate change fraction is low, the candidate neurons will be
trained more and if the fraction is high they will be trained less.

If called with no positional arguments, this method returns the current
candidate change fraction. If called with a positional argument, it will be
coerced to a [Num] and set as the new fraction.

The default cascade candidate change fraction is 0.01, which is equivalent to a
1% change in MSE.

### cascade-candidate-stagnation-epochs

``` raku
# fann_get_cascade_candidate_stagnation_epochs
multi method cascade-candidate-stagnation-epochs returns Num

# fann_set_cascade_candidate_stagnation_epochs
multi method cascade-candidate-stagnation-epochs ( Num() $value ) returns self
```

The number of cascade candidate stagnation epochs determines the number of
epochs training is allowed to continue without changing the MSE by a fraction
of [cascade-candidate-change-fraction](#cascade-candidate-change-fraction).

If called with no positional arguments, this method returns the current
candidate stagnation epochs. If called with a positional argument, it will be
coerced to a [Num] and set as the new candidate stagnation epochs.

The default number of cascade candidate stagnation epochs is 12.

### cascade-output-stagnation-epochs

``` raku
# fann_get_cascade_output_stagnation_epochs
multi method cascade-output-stagnation-epochs returns Num

# fann_set_cascade_output_stagnation_epochs
multi method cascade-output-stagnation-epochs ( Num() $value ) returns self
```

The number of cascade output stagnation epochs determines the number of epochs
training is allowed to continue without changing the MSE by a fraction of
[cascade-output-change-fraction](#cascade-output-change-fraction).

If called with no positional arguments, this method returns the current
output stagnation epochs. If called with a positional argument, it will be
coerced to a [Num] and set as the new output stagnation epochs.

The default number of cascade output stagnation epochs is 12.

### cascade-activation-steepnesses-count

``` raku
# fann_get_cascade_activation_steepnesses_count
multi method cascade-activation_steepnesses_count returns Int
```

Returns the number of activation steepnesses in the list returned by
[cascade-activation-functions](#cascade-activation-functions).

The default number of activation steepnesses is 4.

### cascade-candidate-epochs

``` raku
# fann_get_cascade_min_cand_epochs
# fann_get_cascade_max_cand_epochs
multi method cascade-candidate-epochs returns Range

# fann_set_cascade_min_cand_epochs
# fann_set_cascade_max_cand_epochs
multi method cascade-candidate-epochs (
    Range $value where { not .infinite },
) returns self

multi method cascade-candidate-epochs (
    Int :$min,
    Int :$max,
) returns self
```

The candidate epochs determines the minimum and maximum number of epochs the
input connections to the candidates may be trained before adding a new
candidate neuron.

If called with no positional arguments, this method returns the current
candidate epoch range. If called with a [Range] as a positional argument, it will
be set as the new candidate epoch range. This method can also be called with
a value for the minimum or maximum end of the range as the `:min` and `:max`
named parameters respectively.

The default candidate epoch range is 50..150

### cascade-output-epochs

``` raku
# fann_get_cascade_min_out_epochs
# fann_get_cascade_max_out_epochs
multi method cascade-output-epochs returns Range

# fann_set_cascade_min_out_epochs
# fann_set_cascade_max_out_epochs
multi method cascade-output-epochs (
    Range $value where { not .infinite },
) returns self

multi method cascade-output-epochs (
    Int :$min,
    Int :$max,
) returns self
```

The output epochs determines the minimum and maximum number of epochs the
output connections may be trained after adding a new candidate neuron.

If called with no positional arguments, this method returns the current
output epoch range. If called with a [Range] as a positional argument, it will
be set as the new output epoch range. This method can also be called with
a value for the minimum or maximum end of the range as the `:min` and `:max`
named parameters respectively.

The default output epoch range is 50..150

### cascade-activation-steepnesses

``` raku
# fann_get_cascade_activation_steepnesses
multi method cascade-activation-steepnesses returns List

# fann_set_cascade_activation_steepnesses
multi method cascade-activation-steepnesses (
    CArray[num32] $steepnesses,
) returns self

multi method cascade-activation-steepnesses (
    *@steepnesses,
) returns self
```

If called with no positional arguments, this method returns the array of
activation steepnesses used by the candidates. See
[cascade-num-candidates](#cascade-num-candidates) for a description of which
candidate neurons will be generated by this array.

If called with a [CArray[num32]][CArray] object as the first positional
argument, this method will instead use that as the new value. Alternatively,
the values that would be in that array can be passed as positional arguments
and they'll be internally converted to a C representation to use instead.

In either case, the new array must be just as long as defined by the count
(see [cascade-activation-steepnesses-count](#cascade-activation-steepnesses-count)).

The default activation steepnesses are [ 0.25, 0.50, 0.75, 1.00 ].

### cascade-activation-functions

``` raku
# fann_get_cascade_activation_functions
multi method cascade-activation-functions returns List

# fann_set_cascade_activation_functions
multi method cascade-activation-functions (
    CArray[num32] $functions,
) returns self

multi method cascade-activation-functions (
    *@functions,
) returns self
```

If called with no positional arguments, this method returns the array of
activation functions used by the candidates. See
[cascade-num-candidates](#cascade-num-candidates) for a description of which
candidate neurons will be generated by this array.

If called with a [CArray[num32]][CArray] object as the first positional
argument, this method will instead use that as the new value. Alternatively,
the values that would be in that array can be passed as positional arguments
and they'll be internally converted to a C representation to use instead.

In either case, the new array must be just as long as defined by the count
(see [cascade-activation-functions-count](#cascade-activation-functions-count)).

The default activation functions are [ `FANN_SIGMOID`,
`FANN_SIGMOID_SYMMETRIC`, `FANN_GAUSSIAN`, `FANN_GAUSSIAN_SYMMETRIC`,
`FANN_ELLIOT`, `FANN_ELLIOT_SYMMETRIC`, `FANN_SIN_SYMMETRIC`,
`FANN_COS_SYMMETRIC`, `FANN_SIN`, `FANN_COS` ].

# EXPORT TAGS

AI::FANN exports nothing by default. However, the following enums are
available and can be exported using the `:enum` tag to export *all* enums, or
the `:error` tag to export only the [AI::FANN::Error](#aifannerror) enum.

## AI::FANN::NetType

  * FANN_NETTYPE_LAYER

  * FANN_NETTYPE_SHORTCUT

## AI::FANN::ActivationFunc

The activation functions used for the neurons during training. The activation
functions can either be defined for a group of neurons by calling
[activation-function](#activation-function) with the `:hidden` or `:output`
parameters or it can be defined for a single neuron or layer with the `:layer`
and `:neuron` parameters.

The functions are described with functions where

  * `x` is the input to the activation function

  * `y` is the output

  * `s` is the steepness

  * `d` is the derivation.

The steepness of an activation function is defined in the same way by calling
[activation-steepness](#activation-steepness).

See the documentation for those functions for details.

  * FANN_LINEAR

    Linear activation function.

        -∞ < y < ∞
        y = x⋅s
        d = s

  * FANN_THRESHOLD

    Threshold activation function. Cannot be used during training.

        y = 0 if x < 0
        y = 1 if x ≥ 0

  * FANN_THRESHOLD_SYMMETRIC

    Symmetric threshold activation function. Cannot be used during training.

        y = -1 if x < 0
        y =  1 if x ≥ 0

  * FANN_SIGMOID

    Sigmoid activation function. This function is very commonly used.

        0 < y < 1
        y = 1 / ( 1 + exp( -2⋅s⋅x ) ) - 1
        d = 2⋅s⋅y⋅( 1 - y² )

  * FANN_SIGMOID_STEPWISE

    Stepwise linear approximation to sigmoid. Faster than sigmoid, but a
    little less precise.

  * FANN_SIGMOID_SYMMETRIC

    Symmetric sigmoid activation function, also known as "tanh". This function
    is very commonly used.

        -1 < y < 1
        y = tanh(s⋅x) = 2 / ( 1 + exp( -2⋅s⋅x ) ) - 1
        d = s⋅( 1 - y² )

  * FANN_SIGMOID_SYMMETRIC_STEPWISE

    Stepwise linear approximation to symmetric sigmoid. Faster than symmetric
    sigmoid, but a little less precise.

  * FANN_GAUSSIAN

    Gaussian activation function.

        0 < y < 1
        y = 0 when x = -∞
        y = 1 when x = 0
        y = 0 when x = ∞
        y = exp( -x⋅s⋅x⋅s )
        d = -2⋅x⋅s⋅y⋅s

  * FANN_GAUSSIAN_SYMMETRIC

    Symmetric Gaussian activation function.

        -1 < y < 1
        y = -1 when x = -∞
        y =  1 when x = 0
        y = -1 when x = ∞
        y = exp( -x⋅s⋅x⋅s )⋅2 - 1
        d = -2⋅x⋅s⋅y⋅s

  * FANN_GAUSSIAN_STEPWISE

    Not yet implemented.

  * FANN_ELLIOT

    Fast (sigmoid like) activation function defined by David Elliott.

        0 < y < 1
        y = x⋅s / 2 / ( 1 + |x⋅s| ) + 0.5
        d = s / ( 2 ⋅ ( 1 + |x⋅s| )² )

  * FANN_ELLIOT_SYMMETRIC

    Fast (symmetric sigmoid like) activation function defined by David Elliott.

        -1 < y < 1
        y = x⋅s  / ( 1 + |x⋅s| )
        d = s / ( 1 + |x⋅s| )²

  * FANN_LINEAR_PIECE

    Bounded linear activation function.

        0 ≤ y ≤ 1
        y = x⋅s
        d = s

  * FANN_LINEAR_PIECE_SYMMETRIC

    Bounded linear activation function.

        -1 ≤ y ≤ 1
        y = x⋅s
        d = s

  * FANN_SIN_SYMMETRIC

    Periodical sinus activation function.

        -1 ≤ y ≤ 1
        y = sin( x⋅s )
        d = s⋅cos( x⋅s )

  * FANN_COS_SYMMETRIC

    Periodical cosinus activation function.

        -1 ≤ y ≤ 1
        y = cos( x⋅s )
        d = s⋅-sin( x⋅s )

  * FANN_SIN

    Periodical sinus activation function.

        0 ≤ y ≤ 1
        y = sin( x⋅s ) / 2 + 0.5
        d = s⋅cos( x⋅s ) / 2

  * FANN_COS

    Periodical cosinus activation function.

        0 ≤ y ≤ 1
        y = cos( x⋅s ) / 2 + 0.5
        d = s⋅-sin( x⋅s ) / 2

## AI::FANN::Train

The training algorithms used when training on AI::FANN::TrainData with
functions like [train](#train) with the `:path` or `:data` arguments.  The
incremental training alters the weights after each time it is presented an
input pattern, while batch only alters the weights once after it has been
presented to all the patterns.

  * FANN_TRAIN_INCREMENTAL

    Standard backpropagation algorithm, where the weights are updated after
    each training pattern. This means that the weights are updated many
    times during a single epoch. For this reason some problems will train very
    fast with this algorithm, while other more advanced problems will not
    train very well.

  * FANN_TRAIN_BATCH

    Standard backpropagation algorithm, where the weights are updated after
    calculating the mean square error for the whole training set. This means
    that the weights are only updated once during an epoch. For this reason
    some problems will train slower with this algorithm. But since the mean
    square error is calculated more correctly than in incremental training,
    some problems will reach better solutions with this algorithm.

* FANN_TRAIN_RPROP

    A more advanced batch training algorithm which achieves good results for
    many problems. The RPROP training algorithm is adaptive, and does
    therefore not use the value set with [learning-rate](#learning-rate).
    Some other parameters can however be set to change the way the RPROP
    algorithm works, but it is only recommended for users with insight in how
    the RPROP training algorithm works. The RPROP training algorithm is
    described by [Riedmiller and Braun (1993)](#references), but the actual
    learning algorithm used here is the iRPROP- training algorithm which is
    described by [Igel and Hüsken (2000)](#references) which is a variant of
    the standard RPROP training algorithm.

* FANN_TRAIN_QUICKPROP

    A more advanced batch training algorithm which achieves good results
    for many problems. The quickprop training algorithm uses the
    [learning-rate](#learning-rate) parameter along with other more
    advanced parameters, but it is only recommended to change these advanced
    parameters, for users with insight in how the quickprop training
    algorithm works. The quickprop training algorithm is described by
    [Fahlman (1988)](#references).

* FANN_TRAIN_SARPROP

    This is the same algorithm described in
    [Nicholas and Tamas (1998)](#references).

## AI::FANN::ErrorFunc

Error function used during training.

  * FANN_ERRORFUNC_LINEAR

    Standard linear error function.

  * FANN_ERRORFUNC_TANH

    Tanh error function, usually better but can require a lower learning
    rate. This error function aggressively targets outputs that differ much
    from the desired, while not targeting outputs that only differ a little
    that much. This activation function is not recommended for cascade
    training and incremental training.

## AI::FANN::StopFunc

Stop criteria used during training.

  * FANN_STOPFUNC_MSE

    Stop criterion is Mean Square Error (MSE) value.

  * FANN_STOPFUNC_BIT

    Stop criterion is number of bits that fail. The number of bits means the
    number of output neurons which differ more than the bit fail limit (see
    [bit-fail-limit](#bit-fail-limit)). The bits are counted in all of the
    training data, so this number can be higher than the number of training
    data.

## AI::FANN::Error

Used to define error events on AI::FANN and AI::FANN::TrainData objects.

  * FANN_E_NO_ERROR

    No error.

  * FANN_E_CANT_OPEN_CONFIG_R

    Unable to open configuration file for reading.

  * FANN_E_CANT_OPEN_CONFIG_W

    Unable to open configuration file for writing.

  * FANN_E_WRONG_CONFIG_VERSION

    Wrong version of configuration file.

  * FANN_E_CANT_READ_CONFIG

    Error reading info from configuration file.

  * FANN_E_CANT_READ_NEURON

    Error reading neuron info from configuration file.

  * FANN_E_CANT_READ_CONNECTIONS

    Error reading connections from configuration file.

  * FANN_E_WRONG_NUM_CONNECTIONS

    Number of connections not equal to the number expected.

  * FANN_E_CANT_OPEN_TD_W

    Unable to open train data file for writing.

  * FANN_E_CANT_OPEN_TD_R

    Unable to open train data file for reading.

  * FANN_E_CANT_READ_TD

    Error reading training data from file.

  * FANN_E_CANT_ALLOCATE_MEM

    Unable to allocate memory.

  * FANN_E_CANT_TRAIN_ACTIVATION

    Unable to train with the selected activation function.

  * FANN_E_CANT_USE_ACTIVATION

    Unable to use the selected activation function.

  * FANN_E_TRAIN_DATA_MISMATCH

    Irreconcilable differences between two AI::FANN::TrainData objects.

  * FANN_E_CANT_USE_TRAIN_ALG

    Unable to use the selected training algorithm.

  * FANN_E_TRAIN_DATA_SUBSET

    Trying to take subset which is not within the training set.

  * FANN_E_INDEX_OUT_OF_BOUND

    Index is out of bound.

  * FANN_E_SCALE_NOT_PRESENT

    Scaling parameters not present.

  * FANN_E_INPUT_NO_MATCH

    The number of input neurons in the ANN and data don’t match.

  * FANN_E_OUTPUT_NO_MATCH

    The number of output neurons in the ANN and data don’t match.

# REFERENCES

  * Fahlman, S.E. (1988). "Faster-Learning Variations on Back-Propagation: An
    Empirical Study" in I<Proceedings of the 1988 Connectionist Models Summer
    School>, Morgan Kaufmann.

  * Igel, C., Hüsken, M. (2000) "Improving the Rprop Learning Algorithm" in
    _Proceedings of the Second International ICSC Symposium on Neural
    Computation (NC 2000)_, pp. 115—121. ICSC Academic Press.

  * Nicholas, K.T., Tamas, D.G. (1998) "Simulated Annealing and Weight Decay in
    Adaptive Learning: The SARPROP Algorithm". IEEE Transactions on Neural
    Networks 9(4), pp. 662—668

  * Riedmiller, M., Braun, H. (1993). "A Direct Adaptive Method for Faster
    Backpropagation Leaning: the RPROP Algorithm" in _IEEE International
    Conference on Neural Networks_, pp. 586—591, IEEE.

# COPYRIGHT AND LICENSE

Copyright 2021 José Joaquín Atria

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

[Array]: https://docs.raku.org/type/Array
[CArray]: https://docs.raku.org/language/nativecall#Arrays
[Callable]: https://docs.raku.org/type/Callable
[False]: https://docs.raku.org/type/Bool
[IO::Path]: https://docs.raku.org/type/IO::Path
[Int]: https://docs.raku.org/type/Int
[List]: https://docs.raku.org/type/List
[Num]: https://docs.raku.org/type/Num
[Range]: https://docs.raku.org/type/Range
[SARPROP]: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.47.8197&rep=rep1&type=pdf
[True]: https://docs.raku.org/type/Bool


