Errors with role "currying"
Asked Answered
R

2

7

In the Perl 6 world, currying is an universal term indicating partial instantiation, and it's also used in the world of (parametrized) roles.

However, it's not clear how to actually use it:

role Zipi[::T] {};
class Zape does Zipi[::T] {}

errors with No such symbol T; same if we use simply T when declaring the class, but in this case it's Undeclared name. Eliminating the square brackets and its content yields No appropriate parametric role variant available for 'Zipi', same as leaving the square brackets empty. There seems to be a (kinda) bug report going back to 2012, and of course these examples are taken directly from the source code of CurriedRolehow. Any idea of how this would eventually work or if it's possible to curry parametrized roles by instantiating only some of their parameters?

Riboflavin answered 13/4, 2019 at 7:44 Comment(0)
V
10

The CurriedRoleHOW meta-class represents a role, let's say R, that has been given some set of parameters, for example R[Int,Str]. It's curried in the sense that a role always has an implicit first parameter, which is the class it is eventually composed in to, and so it holds the R and the Int,Str arguments, and then injects them at the point that the role is instantiated (composition time).

One certainly cannot write:

class Zape does Zipi[::T] {}

And expect it to do anything reasonable; ::T is a type capture, and so can only go in a signature. Here, it is being used as an argument to instantiate a role, and is rightly complained about. Further, a class is always a concrete thing, not a generic thing.

It is possible for a role to be curried with a type variable for later instantiation, however. Given a role with two type parameters:

role RA[::T, ::U] {
    method t { T }
    method u { U }
}

We can write another role that fixes one and passes along the other one:

role RB[::T] does RA[T, Int] { }

And then use it like this:

class C does RB[Str] { }
say C.t;
say C.u;

Which has the output:

(Str)
(Int)

In this example, the RA[T, Int] is also modeled by the CurriedRoleHOW metaclass, except this time it has the hole T as well as the implicit ::?CLASS, which I believe achieves that you asked for.

Viscosity answered 13/4, 2019 at 12:17 Comment(0)
E
5

jnthn's answer is authoritative. I'd started this before they answered and feel I may as well post some of it as follows.

In the Perl 6 world, currying is an universal term indicating partial instantiation, and it's also used in the world of (parametrized) roles.

The following is a very minor point, and it seems the boat is far from port now, at least in some internal Rakudo identifiers and in the official P6 doc, but I'd like to note that over the years, most recently in 2017 Larry has seemed to try to nudge folk to not use "currying" this way.

it's not clear how to actually use it:

role Zipi[::T] {}
class Zape does Zipi[::T] {}

The first line is a declaration -- analogous to sub Zipi(::T) {} -- so it uses ::T as a parameter.

The second line is a call -- analogous to Zipi(::T) -- so it uses ::T as an argument.

There seems to be a (kinda) bug report going back to 2012

A search of rt for 'role' doesn't show any open issues mentioning author 'skids'.

these examples are taken directly from the source code of CurriedRolehow

I don't see the ... does role[::T] formulation, with a type capturing ::T, in that file. Either I'm missing what you mean or this was just a bit of confusion about declare vs call given that this does was doing a "call" as part of a declaration.

Any idea ... if it's possible to curry parametrized roles by instantiating only some of their parameters?

Yes, presuming jnthn has correctly understood your question. ;)

Eyeful answered 13/4, 2019 at 12:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.