Wed, 26 Jan 2000 08:34:59 -0000, Chris Angus <[EMAIL PROTECTED]> pisze:
> One thing I dont like, is going through IO, although I guess this
> wouldnt matter so much.
*Of course* it has to be in IO! Loading an external function has
everything to do with I/O.
When you write
fooBar x = (getFunction "foo" x, getFunction "bar" [x])
do you really want to open the external library and load functions
each time fooBar is called? Or do you expect that the runtime system
will cache recently used functions? Argh.
And think about handling I/O errors when loading an external library.
I could accept at most something like this:
do
handle <- openLibrary "filename"
-- or: readLibraryFromString "binary library contents"
f <- loadValue handle "sin"
-- f has type Double -> Double (as inferred from further usage).
-- You can pass f to other functions and use it.
This is something like a variant of hGetLine h >>= readIO, which
reads code evaluating to arbitrary values, probably compiled on the
same platform only.
loadValue has type:
loadValue :: Typeable a => LibraryHandle -> String -> IO a
or with some other class instead of Typeable. The class could even be
magically implicitly instantiated for all types, but it must appear in
the type. loadValue is overloaded, not universally polymorphic. It does
not uniformly work on all types: it raises exception on some types
and succeeds on others. The overloaded type requires disambiguation.
Libraries could possibly be built by compiling standard Haskell modules
with some compiler switch to produce the right format (including
information needed for dynamic typechecking).
We have to solve the problem of other modules used by dynamically
loaded ones.
If you want to load a function and use it polymorphically, probably
local universal quantification is required.
I think that Dynamic's Typeable class could also be derived
automatically - paradoxically I feel that it would be more elegant
then... Also it would be safer and more convenient.
> once I start doing that it seems I have to use glasgow's unsafe IO
> stuff or make all my functions IO-returnric :-/
Probably you can separate reading data from operating on it. Separate
what requires I/O from what does not. Code often gets more readable
when you create intermediate abstract syntax of something instead of
putting all the processing in one place, and laziness will help not
to physically create the whole structure in memory.
Or you really write code that does I/O all the time, and then IO in
their types is perfectly natural.
> I suppose it comes down to
>
> if (performUnsaveIO.f) always returns the same answer to the same arguments
> why does f return (IO a) rather than (a)
It's in the reverse direction only: if it's (a) rather than (IO a),
it should certainly return the same answer for the same arguments.
Functions that need to perform IO for calculation of their results
should have IO type, unless it happens to be safe when they don't
and they really behave like pure functions.
One reason is above: you want more control when it is executed, since
performing I/O interacts with the changing state of the outside world,
can be expensive, can fail, and can cause troubles with polymorphism
(a value produced by IO is lambda-bound and thus monomorphic).
> This is how I feel about commandline arguments.
This is about the only exception where I could ever consider removing
IO from a function that has IO now. But when a global value has type
String, it generally means that it's a compile time constant.
When you really know what you are doing, use unsafePerformIO for
convenience, but on your own risk. Standard libraries should be safe
and not bend rules.
It's good that unsafePerformIO exists, because sometimes it can
be extremely convenient (command line arguments is nothing in
comparison). When reading a long string from an I/O resource (not
using standard readFile or hGetContents) you may want to process
it incrementally; simulating laziness yourself would be a real pain,
would cause changes all over the program, but would be required without
unsafePerformIO. I wish unsafePerformIO was standarized. But it must
not be abused. It's important that it is clearly marked as dangerous.
--
__("< Marcin Kowalczyk * [EMAIL PROTECTED] http://qrczak.ids.net.pl/
\__/ GCS/M d- s+:-- a22 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-