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
[email protected]
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/felix-language