This file was automatically generated from http://svn.pugscode.org/pugs/docs/src/Junc.pod on Wed Jun 6 22:16:47 2007 GMT, revision 16639.
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.
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.
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.
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.
So now we understand 75% of the where clauses for opJunc. Now for
100% closure on where let's understand 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.
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:
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 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.
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.
[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