Lennart Augustsson:
> > If you are happy with the isomorphism
> >
> > (T1 x T2 x ...) <-> (T1 x (T2 x (...)))
>
> But in Haskell these are not isomorphic.
> (a,b,c) is NOT isomorphic to (a,(b,c)), just think about bottom.
Right, thanks. I should have been more precise. On the right, "the"
product is built step-by-step, and each step could fail, whereas
on the left, "the" product is built in one step, taking all components
at once - only one chance to fail (I'm always tempted to think of
bottom at type T as failure to terminate inside T, counting bottom
at T as outside the part of T I'm interested in instead of counting
it as a part of T proper..). In other, words, Haskell treats a product
of a type "a" with a product of a type "b" with a type "c" as
different from a product of three types "a", "b", and "c". Have I
missed anything else so far?
My point was that, in Haskell, instead of a single family of
n-products for each n (indexed by component types) that is built
from smaller products, we have the odd situation that there is one
family of n-products for each n, not built from smaller products,
plus a variety of ways to build structures with n components from
smaller products, all distinguished by their types (due to the
non-associative and multiple-arity constructors, the type records
the order in which a given product structure was built up, e.g.,
(a,((b,a,b),a)) is different from (a,b,a,b,a) and so on..).
This can be quite useful in a dynamically typed language, where
such nested tuple-structures can serve as anonymous data-structures,
but in a statically typed language it is often difficult to operate on
these nests (hence this thread), and we have other ways to build
nested data-structures. So it might (or might not - that's what I'm
trying to find out) be useful to make product (de-)construction
associative (or to provide an associative alternative).
Matt has outlined a not-so-drastic variant, because we both seem
to shy away from the full implications of such a step. Such an
intermediate solution might be more appropriate for Haskell.
Still, I would like to know whether a drastic approach (associative
product with some constraint to guarantee unique decomposition
in pattern matches) could be made to work and what the result
would look like. In contrast to Matt's assumption that (a), for
some expression a, "would of course not be considered a tuple",
I think that all expressions would be (approximations of) tuples,
either explicitly as 0-tuple () or (n+2)-tuple (a,b), or implicitly as
1-tuple (a), if a is not itself of 0- or (n+2)-tuple type (all things
would be products, just the number of components would differ).
Other "oddities" of an associative ',':
- one would think that () simply takes its role as a unit, so that
(),a == a == a,()
but if we know x::() does that imply that x,a == a ?
x could be bottom, and the equations for the unit look strict in their
unit parameter, so probably not;
- despite this first point, n-products might not need to be strict
in their components, only in their structure, whatever that
means exactly..
- (let (a,b) = (1,2,3) in (a,b)) == (1,2,3)
but there are many ways to bind a and b to parts of (1,2,3)
- other surprises?
Yet these are merely unusual (at least I am not used to think
this way about Haskell products), e.g., a type annotation would
suffice to resolve the matching ambiguity and in practice the
types will often be determined by the usage context if the result
of the match is used at all. The strictness properties seem slightly
more puzzling, but perhaps I'm just not looking at the problem
the right way?
So I would like to know: are there any programming languages
with associative products, and is there any real point against
this feature (beyond "unusual")?
In case you don't just like the puzzle for the puzzle's sake, there
are two practical motivations for this:
- the current "products" in Haskell are a pain
- extensible records in TREX use associative commutative
construction and matching, but built-in for one specific
construct (rows); it would be nice if these properties of
constructors could be supported more generally, and
extensible records be built on top of such general support
Just curious,
Claus