Fri, 23 Jun 2000 14:11:04 -0400 (EDT), Chris Okasaki <[EMAIL PROTECTED]> pisze:
> Suppose you have two *classes* that both need/want the same name.
> For example, you may have a class of sequences and a class of finite
> maps that both want to use an empty method. Do you call one emptyS
> and the other emptyFM? Or do you disambiguate using qualified names?
>
> You might say, "Neither! Make a common superclass containing empty
> and anything else common to both sequences and finite maps."
Depends on if there is a chance that the same piece of code would
be used for any of these types, disambiguated by a decision taken
elsewhere.
If yes, I would try to put them in a single class. If not, and if
making a class just for overloading looks silly, unfortunately people
have different opinions whether to add suffixes or use qualified names.
> Unfortunately, this doesn't work because type constructors for
> sequences and finite maps both have different kinds and different
> constraints on their elements.
It does work in this case:
class HasEmpty c where empty :: c
instance HasEmpty [a] where empty = []
instance HasEmpty (FiniteMap k v) where empty = emptyFM
If constraints were needed here, they could be easily added to
instance contexts.
> > I don't like modules that have to be imported qualified.
>
> Can you be more specific?
If some names clash with other modules, there is a tendence to
import the whole module qualified instead of deciding individually,
remembering which names can be used unqualified. Then some names are
unnecessarily long.
Not all modules provide only a type with operations on it.
The module Concurrent provides several kinds of references and streams.
Some of them are reexported from other modules, but QSem and QSemN
both originate from module Semaphore. If
waitQSem :: QSem -> IO ()
waitQSemN :: QSem -> Int -> IO ()
were to share a single name, they would have to be split to two modules
and imported separately instead of by just "import Concurrent".
Maybe even the interface of semaphores could be overloaded, although
it does not give much.
wait :: Semaphore s => s -> IO ()
would be defined as waitQSem or \s -> waitQSemN s 1, and
waitN :: SemaphoreN s => s -> Int -> IO ()
would have only one instance among types provided: waitQSemN. If
somebody wanted to share a semaphore with another language (provided
that concurrency eventually works for foreign calls), a foreign
binding to a foreign semaphore would make another instance.
I don't mind using short names and accidental clash for the name "wait"
between independent modules rarely used together, but I think that
Haskell modules are not good in parametrizing by large pieces of code.
I treat the import list as the function of entities used in the module,
not the opposite.
--
__("< Marcin Kowalczyk * [EMAIL PROTECTED] http://qrczak.ids.net.pl/
\__/ GCS/M d- s+:-- a23 C+++$ UL++>++++$ P+++ L++>++++$ E-
^^ W++ N+++ o? K? w(---) O? M- V? PS-- PE++ Y? PGP+ t
QRCZAK 5? X- R tv-- b+>++ DI D- G+ e>++++ h! r--%>++ y-