Hey perl6 people,

I'm crossposting this message from perl.perl6.language, because I feel it's more
appropriate here. User phi...@free.fr had asked if ADT and GADT will be
available in perl6 any time soon, Carl Mäsak implemented two suggestions (see
quoted text below) and I implemented it as a POC and then as a module.

The module code now lives on github here: https://github.com/timo/ADT/ and is
also available to be panda-installed from modules.perl6.org

I'm looking forward to hearing your comments as well as your issues and pull
requests on github :)
  - Timo

---- 8< ----

On 21.03.2013 17:45, Carl Mäsak wrote:
> [...]
> Using hashes and subclasses: <https://gist.github.com/masak/5213423> Using
> classes and subclasses: <https://gist.github.com/masak/5213563>
> [...]
I came up with a prototype to create those classes like in the second gist
automatically by supplying a haskell-like declaration of the data type.

(skip to the end of the mail for the code)

Here's what it can do:

    my %res = create_adt("Tree = Branch Tree left, Tree right | Leaf Str 
    my \Tree = %res<Tree>;

    # create the tree with named parameters
    my $t =

    # create the tree with positional arguments
    my $t2 =
    say $t2.gist;
    # outputs:  (reformatted for email)
    # Tree.new-branch(
    #        left => Tree.new-branch(
    #             left => Tree.new-leaf(storage => 1),
    #             right => Tree.new-leaf(storage => 2)),
    #        right => Tree.new-leaf(storage => 3))

    my \Branch = %res<Branch>;
    my \Leaf = %res<Leaf>;

    # haskell-style map for the tree
    sub treemap($t, *&code) {
        given $t {
            when Branch {
                return Tree.new-branch(
                        treemap($t.left, &code),
                        treemap($t.right, &code))
            when Leaf {
                return Tree.new-leaf(code($t.storage))

    say treemap($t2, * * 10).gist;
    # outputs:
    # Tree.new-branch(
    #        left => Tree.new-branch(
    #             left => Tree.new-leaf(storage => 10),
    #             right => Tree.new-leaf(storage => 20)),
    #        right => Tree.new-leaf(storage => 30))

There are currently some limitations:

1) there is no compiler support for checking that all cases have been covered,
   but as masak mentioned, I'm confident this can be done with a macro, because
   those run at compile-time basically.
2) you cannot yet use Leaf and Branch for declaring multi subs, because the
   symbols are not there at compile-time, but see below.
3) I have not yet figured out how to properly do pattern matching/decomposing,
   so the names "left", "right" and "storage" need to be supplied in the
   definition unlike in haskell.
4) I'm not sure how to do type parameters (think data Tree A = ...), because
   perl6 has only parametric roles, not parametric classes.

One thing rakudo needs to get for this to be much smoother is support for the
sub EXPORT to return a hash-like of symbols that will be installed in the
caller's package. This would make Tree, Branch and Leaf available as
compile-time symbols, so that multi methods/subs can use them for dispatch.

I mean to turn this into a module for the perl6 modules list some time in the

Finally, here's the runnable code. Feel free to play around with it and tell me
on this mailing list or the IRC channel what further problems (or even
solutions!) you find.


Have Fun!
  - Timo

Reply via email to