The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
= 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