Thanks Gianni and Tobias,

This is very helpful.

One minor follow-up. If I define by signature like this:

my $sgn-walkable = :(Numeric $n --> Numeric);

I could not define Walkable subs like this, could I?

my Walkable $crawlback = ...

Thanks,
Theo

Tobias Boege schreef op 2020-07-20 14:00:
On Mon, 20 Jul 2020, Theo van den Heuvel wrote:
Hi gurus,

after looking at the documentation on Sub, Signature and the raku type
system I find myself unable to constrain the types of functions in the way I
think I need.

The situation: I have a function, let's call in 'walker', whose first
parameter is a callback.
I wish to express that only callbacks with a certain Signature and return
type are acceptable.
Let's say the callback should follow :(Numeric $n --> Numeric). My callback
is going to be more complicated, but for simplicity sake.

I was hoping to be able to use a named type of function with this signature.
I know I can say

my $sig =  :(Numeric $n --> Numeric);

but my attempts to use $sig fail. I found no example of an application
beyond smartmatching.

[...]

but I was hoping for an explicit type, maybe using class, or subset or
roles.
I hope to say soemething like

sub walker(Walkable &callback, ...)

What am I missing here?


You said that you know how to check signatures via smartmatching.
Smartmatching is great, there isn't much to know beyond it. The way
to shoehorn smartmatching into the type system is `subset`:

  subset Walkable of Callable where {
      .signature ~~ :(Numeric --> Numeric)
  };

If your callback signature is more complicated, all the more reason to
give it a name via subset. You can use it now almost like you wanted:

  sub walker (Walkable $w) {
      say $w($_) for 1..10
  }

  walker(-> Numeric $x --> Numeric { $x.sqrt });  # WORKS
  walker(-> $x { $x.sqrt });                      # DOESN'T

You cannot write `Walkable &w` in the signature of &walker because the
combination of a type and the &-sigil apparently means that `&w` should
be Callable and return a Walkable. That's why I use the $-sigil. [*]

Note that if you constrain the signature of a Callable, then you have
to provide the appropriate signature statically, as demonstrated.

Best,
Tobias

[*] N.B. I failed to find a reference for this in the documentation.
I discovered it by writing `sub walker (Int &w)` and provoking a type
checking error which told me that it was expecting `Callable[Int]`.
(That was also my gut feeling.) According to source code, Callable is
a parametric role in Rakudo whose first parameter indeed is the return
type. This is all somewhat nebulous to me (how does the Callable-
parametric way to specify return type compare with smartmatching
against .signature, for example? They don't seem equivalent!), so
I stick with the $-sigil.

Reply via email to