[Haskell] line-based interactive program

Peter Achten P.Achten at cs.ru.nl
Mon Jul 11 09:51:06 EDT 2005


At 05:01 PM 7/9/2005, Wolfgang Jeltsch wrote:
>[..]
>Hello,
>
>the idea is to have different monads for I/O on different resources.  A 
>simple
>example is to have the two monads WorldIO and FileIO and a type 
>FileIOHandle.
>A file is a part of the world.  You have the following functions:
>
>     readChar :: FileIO Char
>     writeChar :: Char -> FileIO ()
>     runFileIO :: FilePath -> FileIO a -> WorldIO (a, FileIOHandle)
>     finishFileIO :: FileIOHandle -> WorldIO ()
>
>readChar and writeChar should be self-explanatory.  At first, runFileIO does
>nothing instead of opening the file and returning the result.  Whenever parts
>of the first component of the result pair are evaluated, as much readChar and
>writeChar actions of the file I/O action are executed as are needed to
>produce the desired parts of the result.  finishFileIO executes the remainder
>of the file I/O and closes the file afterwards.

I am always interested in functional I/O solutions that adopt the 
"world-as-value" paradigm (or the more verbose "explicit multiple 
environment passing" paradigm) that has been exploited in Clean's file I/O 
system and GUI library. Your idea sounds interesting, but your explanation 
above of runFileIO and finishFileIO raises a few questions:

(1) Suppose you have a file with content "abcde" at path p. What does the 
following program fragment yield?
do
         (r1,h1) <- runFileIO p readEntireFile
         (r2,h2) <- runFileIO p readEntireFile
         return hd r1 : hd r2
where readEntireFile reads the entire file and returns it as a string. I 
can imagine several results: [a,a], [a,b], [a,_|_], [_|_,_|_], _|_.

(2) Can a writer interfere with a reader? Let writeFile :: Integer -> Char 
-> FileIO () write n times a given char to a file. What is then the result 
of:
do
        (r1,h1) <- runFileIO p readEntireFile
         (r2,h2) <- runFileIO p (writeFile 5 'X')
         return (r2,r1)
Does it yield ((),"abcde"), ((),"XXXXX"), (_|_,"abcde"), or _|_? What is 
the result when (r1,r2) is returned instead of (r2,r1)?

(3) One of the advantages of an explicit environment passing scheme is that 
you get true functional behaviour of programs. As an example, in Clean you 
can write a function that tests the content of a file, and if successfull 
proceeds with the remainder, and otherwise with its argument file. (Clean 
code ahead):
parseInt :: Int File -> (Int,File)
parseInt n file
     | ok && isDigit c = parseInt (n*10+d) file1
     | otherwise       = (n,file)
where (ok,c,file1)    = sfreadc file
       d               = toInt c - toInt '0'
Does your scheme allow such kind of behavior?

>An extended version of this approach shall also handle situations like pure
>reading of files where not all read operations have to be carried out if they
>are not needed to produce the desired result.  In this case, finishFileIO
>would just close the file without previously executing the remainder of the
>file I/O action.  The problem is that it cannot be assured that as yet
>unevaluated parts of the result aren't evaluated after exeuction of
>finishFileIO.  Therefore, if evaluation after finishing demands the execution
>of read operations these operations shall not actually be executed but
>instead _|_ shall be returned.

This scheme forces the programmer to carefully plan calls to finishFileIO. 
Let's assume that the readEntireFile is a pure reader of files, then the 
program fragment:
do
         (r1,h1) <- runFileIO p readEntireFile
         finishFileIO h1
         ... computations that use r1 ...
always use _|_ for r1. It is not always the case that
do
         (r1,h1) <- runFileIO p readEntireFile
         ... computations that use r1 ...
         finishFileIO h1
solves the problem, in particular when the computations that use r1 are 
pure functions. You'd have to "connect" r1 to the WorldIO monad before 
doing finishFileIO on h1.

How can you tell a function is a pure reader?

>I also plan to provide a general framework for working on parts of the state
>interleaved with working on the remainder of the state.  The framework shall
>be hierarchical in the sense that you cannot just work on parts of the world
>but also on parts of parts of the world and so on.  It will probably use
>multi-parameter classes to describe which thing is part of which other thing.
>
>When my diploma thesis and the corresponding talk are finished (which will
>probably at the end of September), I may post a more detailed description on
>this list and also provide some code.

Good luck with your thesis. I'd like to see the final result.

Regards,
Peter Achten

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org//pipermail/haskell/attachments/20050711/512fe5ac/attachment-0001.htm


More information about the Haskell mailing list