rakunqp

Errors with role "currying"


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?


Solution

  • 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.