I have just more or less eliminated the BEXPR_get_n combinator from Felix.
This term:

        BEXPR_get_n (index, data)

was used to apply a projection to some data. I replaced that with

        BEXPR_apply (index,data)

but the result isn't very nice. In Felix terms carry types around:

        (expression, type)

and the type is supposed to be a cached value that could be computed
by analysis of an expression structure, but with the change above
I have to rely on the type to distinguish a projection like

        (case 1 of int * double) (42,23.2) // projection

from a constructor like:

        (case 1 of int * double) 23.2 // injection


Actually I observe that the "generalised projection" is actually a projection
followed by an injection:

        int * double --> int + double

can be found by first applying the projection, then the injection. Such a 
pairing
is useful, because it allows you to use a loop through the projections of 
a tuple and construct a homogenous list of the components.

So my inclination now is to introduce:

        BEXPR_proj of int * type * type

so that

        BEXPR_proj (n,domain, codomain)

is the canonical projection from domain to codomain, for example:

        BEXPR_proj (1, BTYP_tuple (int; float), float))

is the projection above. The difference between this an BEXPR_get_n is that
the projection function is a separate term, unapplied, so

        BEXPR_get_n (BEXPR_case n .., arg) = BEXPR_apply (BEXPR_proj (n,..), 
arg)

This suggests

        BEXPR_case (1, BTYP_sum (int; float)) 

be renamed to 

        BEXPR_inj ....

because it is, similarly, an injection function that has to be applied.

This leaves an interesting condundrum. Consider:

        typedef bool = 2;
        val true = case 1 of 2;
        val false = case 0 of 2;


Now, technically the injection is:

        true = fun () => ...

that is, technically the injection should take a unit argument. However Ocaml, 
and Felix,
have a distinction between non-constant type constructors and constant ones.
A constructor that would take a unit argument is "simplified" by allowing it to 
be
the value that would be produced by applying the injection to ().

Another example:

        union list = Empty | Cons of int * list

Technically it SHOULD be:

        union list = Empty of unit | Cons of int  * list

because Empty is really an injection function so it has to have an argument.
But we gloss over that, so instead of writing

        #Empty 
or
        Empty ()


we use Empty as the name for what these applications would produce.
[Somehow, we're changing the injection from

        empty : 1 -> list

to

        empty: 0 -> list

by removing the need for the argument...]


Anyhow this suggests I use

        BEXPR_ case (n, T) 

for constant constructors, a shorthand if you like for

        BEXPR_apply (BEXPR_inj (n, T), BEXPR_tuple [])

i.e. we still have the injection function for constant constructors,
which are applied to unit value, but use the case notation as the
name of the result, and a shorthand for the application.

I have to also show we have a couple of other terms to make a 
complete set. We have tuple constructor

        BEXPR_tuple [value, value, value ....]

to make tuples (no point having a projection if you cannot make
something to project from).

We have two terms to pull sum types apart:

        BEXPR_case_index (v)

returns the index number of a sum value (i.e. the discriminant).
And,

        BEXPR_case_arg v

rips out the value (injection function argument). There's also

        BEXPR_match_case

which is used in pattern matching. Also we have another way to 
make and break tuples like a list instead of all at once.


        BEXPR_tuple_cons
        BEXPR_tuple_head
        BEXPR_tuple_tail

and there's a thing called a variant which is the dual of a record
but uses a *string* as a run time index instead of an integer:

        BEXPR_variant (string, value)

which, like a record, allows some arbitrary combination of variants
to be considered a type (kind of like a universal union with the
run time type indicator being a string).

There's one more term that could be added:

        BEXPR_int (n)

Just as, for example

        23

is a type, namely a sum of 23 units, so it has 23 cases and is similar
to modular arithmetic base 23, there is a sum of countably infinite
units, which is just the integers: actually natural numbers, but we need
the negatives to make it into a cyclic group.

It's very tempting to add this to the core language, instead of relying
on the library: similarly for bool, because the compiler itself wants
to do both integral and boolean calculations, and it can't (because they're
user defined). In fact BEXPR_not is already in there.


--
john skaller
skal...@users.sourceforge.net
http://felix-lang.org




------------------------------------------------------------------------------
LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99!
1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint
2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes
Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13. 
http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to