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.

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk

Reply via email to