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 storage"); my \Tree = %res<Tree>; # create the tree with named parameters my $t = 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)))); # create the tree with positional arguments my $t2 = Tree.new-branch( Tree.new-branch( Tree.new-leaf(1), Tree.new-leaf(2)), Tree.new-leaf(3)); 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 Future. 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. https://gist.github.com/timo/5226114 Have Fun! - Timo