= NAME
Junc.pod - explanation of how Junc.hs works
= OVERVIEW
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]
= HOW THE MODULE WORKS
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.
== 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.
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
=== sameType and partition
`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 {file: 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
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
== isTotalJunc, isPartialJunc (in the context of ApplyArg)
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.
= TODO
= errata
[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().
== argsCollapsed
= AUTHOR
metaperl with help from Cale, Igloo