=head1 NAME

Junc.pod - explanation of how Junc.hs works

=head1 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:

L<http://dev.perl.org/perl6/synopsis/S09.html>

=head1 HOW THE MODULE WORKS

First we load in the C<Internals> and the abstract syntax tree,
C<AST>.

The first thing to understand is how C<opJunc> works. It's just the
first function in the file, but it is important, so let's
get down to business.



=head2 opJunc

The type signature of this function is

 opJunc :: JuncType -> [Val] -> Val

which means it takes a C<JuncType> and a list of type C<Val> and
returns an element of type C<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

=head3 sameType and partition

C<js> and C<vs> are defined by a call to C<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, C<js> turns out to be all elements which are
the same as the type we passed in and C<vs> are the ones which are not
the same type. How does C<sameType> work? The call to sameType is using
pattern matching. C<VJunc>, if you look in F<AST.hs>, is part of some
punnery being used in the C<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 C<where> clauses for C<opJunc>. Now for
100% closure on C<where> let's understand C<joined> :

=head3 joined

  joined = unionManySets $ map (\(VJunc s) -> juncSet s) js 

Well, we know that C<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
C<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 C<juncSet> fields from a
list of values of type C<VJunc>. Then this list is passed to
C<unionManySets>: 

L<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 C<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

=head2 isTotalJunc, isPartialJunc (in the context of ApplyArg)

Both C<isTotalJunc> and C<isPartialJunc> operate on a single piece of data
of type C<ApplyArg>. The C<ApplyArg> value slot must be of type
C<VJunc> or either function will return False. 

C<isTotalJunc> tests to see if the VJunc value slot is of type C<JAll>
or C<JNone>. Note that unlike most tests which return C<True> if their
test passes, this function (and C<isPartialJunc>) return the negation
of the C<argCollapsed> slot.

C<isPartialJunc> tests to see if the VJunc value slot is of type C<JOne>
or C<JAny>. It also returns the negation
of the C<argCollapsed> slot if this test passes and False otherwise.

=head1 TODO


=head1 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().

=head2 argsCollapsed



=head1 AUTHOR

metaperl with help from Cale, Igloo