Junxian J Liu raises the question:

|               IS THE I/O SYSTEM IN HASKELL ADEQUATE?   

to which Lennart Augustsson replies:

| I think the answer is: NO! 
| What you want to do cannot be done in Haskell.

I don't agree with this.  Certainly for the example given, it is possible
to code the required problem in Haskell, as Junxian J Liu indicated in
the original posting:

|  > main = readChan "data" abort
|  >        (\ s -> appendChan "stdout" (result s) abort done
|  >                where
|  >                ns = map read (lines s)
|  >                n  = length ns
|  >                ... ...
|  >        )

If adequacy means that the problem can be solved, then Haskell I/O is
certainly adequate for this example.  On the other hand, you may well
argue that it is inconvenient to write programs in this way, or that
the resulting programs (for larger examples) are too complicated for
our current selection of compilers.  These are different issues (but
just as important from the user's point of view).

Lennart's suggestion seems quite attractive:

| If you are more interested in getting a running program than writing
| in standard Haskell you might want to consider using hbc.  It contains
| a module IO which (among other things) has the function
|         openFile :: String -> Either String String
| which given a file name returns the contents of the file or an error
| message.  This module is not written in Haskell (since it's impossible to
| do that).

I would be very worried if you could write it in Haskell.  An
implementation of standard Haskell I/O should preserve referential
transparency, but can you still guarantee this if you also include
something like openFile?  For example, is the program (for some
suitable f to handle values of type Either a b):

    main = appendChan stdout (f (openFile "myfile"))  exit $
           writeFile "myfile" "a string"              exit $
           appendChan stdout (f (openFile "myfile"))  exit $
           done

equivalent to:

    main' = appendChan stdout contents     exit $
            writeFile "myfile" "a string"  exit $
            appendChan stdout contents     exit $
            done
            where contents = f (openFile "myfile")

?

Perhaps you could recover referential transparency by keeping a list
of files that have been openFile'd and another of those that have
been writeFile'd as part of the state in the semantics of I/O:
the idea here would be to prohibit both:

 o  openFile'ing a file which has already been writeFile'd, and

 o  writeFile'ing a file which has already been openFile'd.

I think this fixes the problem in the example above, but I'm not
convinced that it would work in general.  Can anyone think of a
counterexample?

Mark

Reply via email to