Junc.pod - explanation of how Junc.hs works
I am a fledgling Haskell programmer having just finished reading YAHT. For some reason, I was attracted to understanding Junc.hs and so will document its workings.
Junc.hs is the main code for implementing Perl 6 Junctions:
http://dev.perl.org/perl6/synopsis/S09.html
First we load in the Internals and the abstract syntax tree, AST.
Internals
AST
The first thing to understand is how opJunc works. It's just the first function in the file, but it is important, so let's get down to business.
opJunc
The type signature of this function is
opJunc :: JuncType -> [Val] -> Val
which means it takes a JuncType and a list of type Val and returns an element of type Val. More properly this function returns an element of type VJunc, but you cannot specify that a function returns a subtype only a type.
JuncType
Val
Here is it's definition. Let's understand it:
opJunc :: JuncType -> [Val] -> Val opJunc t vals = VJunc $ Junc t emptySet (joined `union` mkSet vs) where joined = unionManySets $ map (\(VJunc s) -> juncSet s) js (js, vs) = partition sameType vals sameType (VJunc (Junc t' _ _)) = t == t' sameType _ = False
js and vs are defined by a call to partition, which takes a list of elements and returns a pair of lists in which the first list is those elements which satisfied a predicate and the second list is those which failed. So, js turns out to be all elements which are the same as the type we passed in and vs are the ones which are not the same type. How does sameType work? The call to sameType is using pattern matching. VJunc, if you look in AST.hs, is part of some punnery being used in the Val enumerated set type. VJunc is both a data constructor and it receives a parameter of type VJunc which is defined further down. Pattern matching the first element of a value of type VJunc extracts the type of the VJunct. If the two types are equal, then we have the same type.
js
vs
partition
sameType
VJunc
So now we understand 75% of the where clauses for opJunc. Now for 100% closure on where let's understand joined :
where
joined
joined = unionManySets $ map (\(VJunc s) -> juncSet s) js
Well, we know that js is the list of values that are the same type of as the passed-in type. Now, this function:
(\(VJunc s) -> juncSet s)
might look a little funny but it's simple. We are pulling the juncSet slot from a value (namely s) whose type is VJunct. In Perl5 you might do $s->{juncSet} for the same effect.
juncSet
So, all the map is doing is extracting the juncSet fields from a list of values of type VJunc. Then this list is passed to unionManySets:
unionManySets
http://www.haskell.org/ghc/docs/5.04.3/html/base/Data.Set.html#unionManySets
which takes a list of Sets and turns them into a single set.
Now that we know what each of the where clauses does for the main clause, let's understand the main clause:
opJunc t vals = VJunc $ Junc t emptySet (joined `union` mkSet vs)
in the context of a real call to it:
opJuncAll = opJunc JAll
Both isTotalJunc and isPartialJunc operate on a single piece of data of type ApplyArg. The ApplyArg value slot must be of type VJunc or either function will return False.
isTotalJunc
isPartialJunc
ApplyArg
isTotalJunc tests to see if the VJunc value slot is of type JAll or JNone. Note that unlike most tests which return True if their test passes, this function (and isPartialJunc) return the negation of the argCollapsed slot.
JAll
JNone
True
argCollapsed
isPartialJunc tests to see if the VJunc value slot is of type JOne or JAny. It also returns the negation of the argCollapsed slot if this test passes and False otherwise.
JOne
JAny
[20:58] <autrijus> it will take some used to at first [20:58] <autrijus> but the context will make it clear [20:58] <autrijus> cool with it? [20:59] <autrijus> juncSet is used for all junctions [20:59] <metaperl> yes [20:59] <autrijus> juncDup is only used for one() [20:59] <autrijus> the reason is that one() cannot be represent as one set [20:59] <autrijus> must use two sets.
* autrijus said none() originally, but it should be one().
metaperl with help from Cale, Igloo
To install Perl6::Pugs, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Perl6::Pugs
CPAN shell
perl -MCPAN -e shell install Perl6::Pugs
For more information on module installation, please visit the detailed CPAN module installation guide.