David Barton writes:
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.
and then goes on:
I am not sure how the parametric type class ideas tie into all this
(if they do at all).
Well, parametric type classes can give you a type-systematic basis for doing
this. Using some of the notation of our Lisp and FP '92 paper, you could define:
class f :: Function a b where -- the class of functions
($) :: f -> a -> b -- 'apply' is expressed as infix '$'.
inst a -> b :: Function a b where -- '->' is the classical instance type
f $ x = f x
class (f :: Function a b, a :: Ix) => f :: FiniteFunction a b where
dom: f -> (a, a)
-- the class of finite functions
-- (with rectangular domains),
-- defined as a subclass of Function
inst Array a b :: FiniteFunction a b where
arr $ x = arr ! x -- an instance of a finite function
dom arr = bounds arr
You might object that all we did was exchange one awkward symbol for indexing
(!) by another ($). To be able to use juxtaposition for array indexing, we need
to get a "handle" on juxtaposition. One way to do that would be by decreeing:
f x is syntactic sugar for f$x .
In that case we need to adapt the instance declaration of arrow:
inst a -> b :: Function a b where
f $ x = primApply f x
And we are done.
However, I am not sure we want to do that, since principal types become very
unwieldy. For instance, if composition were defined as usual
(f . g) x = f (g x) ,
its principal type would be
(ft :: Function b c, gt :: Function a b) => ft -> gt -> a -> c.
[Aside: This is another example where multiple argument type classes lead to
ambiguities, but parametric type classes don't.]
The principal type is what it should be, since each of f and g can be an array
instead of a function (or it can be some other instance of class Function). You
see, the cost of generality is increased complexity of many principal type
expressions. I am not sure whether this cost is worth the gains (it might be).
On the other hand, having an explicit overloaded infix operator for application
does not seem to complicate anything.
-- Martin Odersky