Haskell Language Design Questions
Marcin 'Qrczak' Kowalczyk
30 Dec 2000 09:34:22 GMT
Sat, 30 Dec 2000 14:50:04 +1100, Fergus Henderson <firstname.lastname@example.org> pisze:
> It's just something that didn't make it into Haskell 98.
> Hugs and ghc offer a language extension for that.
> It will almost certainly be in the next revision of Haskell. See
Existential quantification is not always necessary to obtain an
equivalent of dynamic binding. Dynamic binding is often used instead
of function closures or IO action closures, especially in languages
which lack real closures.
An object of the abstract type "output IO stream" is equivalent to
a record (tuple, whatever) of values of types like
Char -> IO () -- write a character
String -> IO () -- write a string
IO () -- flush
IO () -- close
"Dynamic binding" is a fancy way of saying that the function to be
called will be chosen at runtime. So we have exactly this, expressed
in a simpler way.
OO languages provide subtyping and inheritance. This is harder.
Subtyping done by explicit coercions up can be done, but it's tedious
to write (my new record scheme proposal tries to help here), and it's
impossible to coerce down. Inheritance can be done by delegation.
It does not work to express everything like OO languages usually do,
because they are not typesafe. That's why (IMHO) that OO languages are
usually dynamically typed. OO-like subtyping is usually not able to
accurately express binary methods or the requirement that an argument
must provide several interfaces at once.
Haskell's classes should be left for constraints on types (as opposed
to values). I want to sort a list, I compare elements with each
other. It does not make sense to say that an element is comparable.
Comparable with what? A _type_ can be comparable (i.e. ordered),
or the ordering itself may be expressed as an object, but it does
not belong to objects being compared. It follows that it does not
make sense to have "a heterogeneous collection of comparable objects"
or casting an object up to the type "comparable".
But I might not care if the fact that something is a stream open for
writing is a property of its type which is not statically known (as
when stream is modelled as a class) or a property of all objects of the
given type which is concrete (as when stream is modelled as a record
of functions) - because I usually work with one such object at a time.
When it's expressed as a class, I gain the possibility of extracting
from the same object at different places properties belonging to
different interfaces, without explicit coercions. But it is necessary
to use existential quantification for heterogeneous collections.
When it's expressed as a record of functions, all streams are flattened
to a single interface, it is more convenient to use but the information
about the exact kind of stream is not available.
These approaches can be mixed. With my new record scheme proposal
it is more convenient to introduce a class of types of objects from
which the interface of a stream open for writing (expressed as a
record of functions) can be extracted. This class needs not to be
explicitly defined (only the record of functions). Stream operations
can also be seen as provided by the object itself instead of always
going through the extracted interface.
__("< Marcin Kowalczyk * email@example.com http://qrczak.ids.net.pl/
^^ SYGNATURA ZASTĘPCZA