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