Should BitC incorporate comprehensions?/

I'm embarrassed to say that the notion of "comprehensions" confused me for
a long time. It's a big word suggesting something complicated to me that
turns out to mean something very simple. For allocation-sensitive
applications, many comprehensions will turn out not to be usable, but they
are still a useful syntactic construct for application purposes. Actually,
I haven't thought very hard about which comprehension-driven allocations
can be eliminated, so maybe my concern isn't yet justified.

My personal opinion is that comprehensions are useful even if we only do
them for a few commonly used types (e.g. lists, vectors, lazy sequences).
My concern is that by introducing comprehensions for these types, we
effectively move the convenience syntax for these types back into the
language core. Right now, nearly all of that convenience syntax is handled
with predefined rules in the mixfix engine, which simplifies parsing quite
a lot by handling it all in a uniform way.

Questions:

1. Do we feel that comprehensions are useful enough to warrant inclusion?
2. Do we agree that comprehensions seem prone to entail allocation, in
which case there are some kinds of codes that may need to avoid them?
3. Is there some way to generalize our handling of convenience syntax in
order to generalize our handling of comprehensions? In particular, is there
some trick similar to "mixfix wrapping a type constructor is both a type
expression and a pattern expression" that we can adopt in this case to
allow more generalized extensions to convenience construction syntax?

F# has a somewhat interesting take on extensible comprehensions in the form
of "Computation Expresions":

http://research.microsoft.com/pubs/217375/computation-zoo.pdf


I'm planning to read that paper again while asking myself "how much of this
wouldn't be necessary if F# had mixfix?" I'm very clear that computation
expressions introduce some new constructs (notably some syntactic support
for incrementally generated sequences via co-routines). What I'm not clear
about is how to think about the types in something like the following list
comprehension:

[ toUpper c | c <- (s : String) ]


Here's what makes me unhappy about this construct: it's syntax driven
rather than type driven. It seems to me that the right reading of this
construct ought to be something like

someConstructor (generator yielding BoundedList 'nat 'a) -> someType 'a


and in this case the generator is something like:

map (fn (c) = toUppser c) (c <- (s : String))


Where:

c-> (s : String)


is itself a generator producing a result of type BoundedList 'nat char, and
we can readily imagine a map that maps from one bounded list to another. So
far so good, but then we are left with something of the form

[ e : BoundedList 'Nat char ]


which is presumably a mixfix wrapper of

list (e:BoundedList 'Nar char)


And hello! What's that? Is that really a distinguished constructor? If the
output here has type BoundedList 'a, that's not so bad. We just need to
define it somewhere, and it can certainly be something built-in for those
types that are internally variadic.

Offhand, it seems to me that the comprehension notion really only works for
types having some distinguished constructor with the signature

(BoundedList 'nat 'a) -> type [optional type arguments including 'a]


Does that seem about right?

If so, then I suspect our mixfix support may need some tweaks, but I think
we may be close to generalizing comprehensions...



shap
_______________________________________________
bitc-dev mailing list
[email protected]
http://www.coyotos.org/mailman/listinfo/bitc-dev

Reply via email to