Paul Hudak writes, as long ago as August 6th:
>Of course, what we REALLY need is a rich enough overloading mechanism
>to allow using the same syntax to support arrays, lists, etc. Some
>people I know are working on that...
Well, we at Intermetrics have been working on incorporating Haskell
into a hardware description language for the description of microwave
hardware (MHDL) for about a year now. I have not been able to post to
this list as I would like; I hope to try to do more of that in the
near future. On this one subject, I think I have something to say.
As a preface: this is not primarily a format issue (although, I
admit, that I started thinking about this issue when the microwave
engineers rose up en masse and smote me about the head and shoulders
for the use of the "!" operator for array subscription). It is also
the result of eighteen months worth of Al Gilman (local to our office)
trying to pound into my head the importance of viewing arrays, and
tables, as alternative mechanisms of defining functions. Credit where
credit is due: thanks, Al!
I submit (for everyone's consideration) that arrays should not be
distinct from functions; indeed, that an array is an alternative
mechanism for defining a function. "Indexing" an array is an artifact
of the Fortran mechanism of viewing an array. An array should be
evaluated just as a function is evaluated.
I further submit (IMHO) that this definition is much closer to the
normal definition of what a function is. My first abstract algebra
class defined a function as a set of ordered pairs, and the first
examples were lists of ordered pairs. The only mechanism that Haskell
allows for the moment to reproduce this definition is a very large
case statement (that I can think of: any corrections?). I think this
is a mistake. We should be able to define a function by listing the
ordered pairs in the function: i.e., by providing an association list.
I also think this view of arrays would require very little change to
the language itself. For example:
array :: (Ix a) => (a,a) -> [Assoc a b] -> a -> b
bounds :: (Ix a) => (a -> b) -> (a,a)
indices:: (Ix a) => (a -> b) -> [a]
indices = range . bound -- Still!!!
elems :: (Ix a) => (a -> b) -> [b]
elems a = [a i | i <- indices a]
and so on.
The only problematic element here is the bounds function. I submit
that this is a natural function to apply to _any_ function whose first
argument is constrained by (Ix a). Indeed, I would like to consider
this in the light of the broader discussion concerning subtypes. The
bounds function makes sense on any constrained domain for a function
(and should diverge if that constraint does not make sense, as for
Of course, this is simply the expedient of making the array function
equal to the function in the MkArray definition. The MkArray
definition has the bounds explicitly in the data structure (as given
by the first element). The only great change I am suggesting is that
it makes sense for this range to be an implicit part of any function
whose first argument is in Ix.
There is actually a more general issue here, which comes up if we
regard the problem of defining bounds and array in the standard
prelude, as is done now (without reference to a "prim" prefix). There
can be many different representations of a function, or ways of
defining a function (obviously). The present Haskell definition
caters to this just fine, except for the fact that we cannot extend
the definition of function application. The present MkArray
definition is just fine, with the bounds of the function an explicit
part of the data representation. However, I want to be able to treat
these arrays as functions in every other sense: I want to evaluate
them as functions, have functional composition defined, curry the
function invocations, and so on.
The problem with this is the notation of the new functions, and the
relationship between those functions and other functions. Is the
appropriate type signature for the array function as given above, or
as in the standard prelude? What does this do for the ability to
write functions that only apply to array functions, and not other
functions? Is some type of extension to the constraint mechanism the
best way to handle this?
I am not sure how the parametric type class ideas tie into all this
(if they do at all). I am also not as well read as I should be in the
field of functional programming in general. Has anyone else suggested
looking at arrays as functions? Has anyone thought of the general
problem of alternative function representations? Sorry to be so
elementary; it is one of the prices to pay for limited time to do the
reading I should do as a matter of course.
In any case, I think it is high time that we free ourselves of an
imperative view of arrays and functions, and the differences between
Well, now I will see how many serious gaffes I have made......