<html>
<body>
At 05:01 PM 7/9/2005, Wolfgang Jeltsch wrote:<br>
<blockquote type=cite class=cite cite="">[..]<br>
Hello,<br><br>
the idea is to have different monads for I/O on different
resources. A simple <br>
example is to have the two monads WorldIO and FileIO and a type
FileIOHandle. <br>
A file is a part of the world. You have the following
functions:<br><br>
readChar :: FileIO Char<br>
writeChar :: Char -> FileIO ()<br>
runFileIO :: FilePath -> FileIO a -> WorldIO (a,
FileIOHandle)<br>
finishFileIO :: FileIOHandle -> WorldIO
()<br><br>
readChar and writeChar should be self-explanatory. At first,
runFileIO does <br>
nothing instead of opening the file and returning the result.
Whenever parts <br>
of the first component of the result pair are evaluated, as much readChar
and <br>
writeChar actions of the file I/O action are executed as are needed to
<br>
produce the desired parts of the result. finishFileIO executes the
remainder <br>
of the file I/O and closes the file afterwards.</blockquote><br>
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:<br><br>
(1) Suppose you have a file with content "abcde" at path p.
What does the following program fragment yield?
<dl>
<dd><tt>do
<dd> (r1,h1) <- runFileIO p
readEntireFile
<dd> (r2,h2) <- runFileIO p
readEntireFile
<dd> return hd r1 : hd
r2</tt>
</dl>where readEntireFile reads the entire file and returns it as a
string. I can imagine several results: [a,a], [a,b], [a,_|_], [_|_,_|_],
_|_.<br><br>
(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:
<dl>
<dd><tt>do
<dd> (r1,h1) <- runFileIO p
readEntireFile
<dd> (r2,h2) <- runFileIO p
(writeFile 5 'X')
<dd> return (r2,r1)</tt>
</dl>Does it yield ((),"abcde"), ((),"XXXXX"),
(_|_,"abcde"), or _|_? What is the result when (r1,r2) is
returned instead of (r2,r1)?<br><br>
(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):
<dl>
<dd><tt>parseInt :: Int File -> (Int,File)
<dd>parseInt n file
<dd> | ok && isDigit c = parseInt (n*10+d)
file1
<dd> | otherwise =
(n,file)
<dd>where (ok,c,file1) = sfreadc file
<dd>
d
= toInt c - toInt '0'</tt>
</dl>Does your scheme allow such kind of behavior?<br><br>
<blockquote type=cite class=cite cite="">An extended version of this
approach shall also handle situations like pure <br>
reading of files where not all read operations have to be carried out if
they <br>
are not needed to produce the desired result. In this case,
finishFileIO <br>
would just close the file without previously executing the remainder of
the <br>
file I/O action. The problem is that it cannot be assured that as
yet <br>
unevaluated parts of the result aren't evaluated after exeuction of
<br>
finishFileIO. Therefore, if evaluation after finishing demands the
execution <br>
of read operations these operations shall not actually be executed but
<br>
instead _|_ shall be returned.</blockquote><br>
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:
<dl>
<dd><tt>do
<dd> (r1,h1) <- runFileIO p
readEntireFile
<dd> finishFileIO h1
<dd> ... computations that use
r1 ...</tt>
</dl>always use _|_ for r1. It is not always the case that
<dl>
<dd><tt>do
<dd> (r1,h1) <- runFileIO p
readEntireFile
<dd> ... computations that use
r1 ...
<dd> finishFileIO h1</tt>
</dl>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.<br><br>
How can you tell a function is a pure reader?<br><br>
<blockquote type=cite class=cite cite="">I also plan to provide a general
framework for working on parts of the state <br>
interleaved with working on the remainder of the state. The
framework shall <br>
be hierarchical in the sense that you cannot just work on parts of the
world <br>
but also on parts of parts of the world and so on. It will probably
use <br>
multi-parameter classes to describe which thing is part of which other
thing.<br><br>
When my diploma thesis and the corresponding talk are finished (which
will <br>
probably at the end of September), I may post a more detailed description
on <br>
this list and also provide some code.</blockquote><br>
Good luck with your thesis. I'd like to see the final result.<br><br>
Regards,<br>
Peter Achten<br>
</body>
<br>
</html>