1-- -------------------------------------------------------- [ Effectful FileIO ]
9||| A Dependent type to describe File Handles. File handles are
10||| parameterised with the current state of the file: Closed; Open for
11||| reading; and Open for writing.
14data OpenFile : (m : Mode) -> Type where
15 FH : File -> OpenFile m
17openOK : Mode -> Bool -> Type
18openOK m True = OpenFile m
21-- ------------------------------------------------------------ [ The Protocol ]
23||| Here the protocol for resource access is defined as an effect.
24||| The state transitions diagram for the protocol is as follows:
28||| empty; read; write; // States
30||| empty -> read [label="Open R"];
31||| read -> empty [label="Close"];
32||| read -> read [label="ReadLine"];
33||| read -> read [label="EOF"];
35||| empty -> write [label="Open W"];
36||| write -> empty [label="Close"];
37||| write -> write [label="WriteLine"];
40data FileIO : Effect where
41 ||| Open a file with the specified mode.
43 ||| Opening a file successful moves the state from 'empty' to the
44 ||| specified mode. If not successful the state is still 'empty'.
46 ||| @ fname The file name to be opened.
47 ||| @ m The file mode.
48 Open : (fname: String)
50 -> sig FileIO Bool () (\res => case res of
56 ||| Closing a file moves the state from Open to closed.
57 Close : sig FileIO () (OpenFile m) ()
59 ||| Read a line from the file.
61 ||| Only files that are open for reading can be read.
62 ReadLine : sig FileIO String (OpenFile Read)
64 ||| Write a string to a file.
66 ||| Only file that are open for writing can be written to.
67 WriteString : String -> sig FileIO () (OpenFile WriteTruncate)
71 ||| Only files open for reading can be tested for EOF
72 EOF : sig FileIO Bool (OpenFile Read)
74-- ------------------------------------------------------------ [ The Handlers ]
76--- An implementation of the resource access protocol for the IO Context.
77implementation Handler FileIO IO where
78 handle () (Open fname m) k = do Right h <- openFile fname m
79 | Left err => k False ()
81 handle (FH h) Close k = do closeFile h
83 handle (FH h) ReadLine k = do Right str <- fGetLine h
84 -- Need proper error handling!
85 | Left err => k "" (FH h)
87 handle (FH h) (WriteString str) k = do Right () <- fPutStr h str
88 | Left err => k () (FH h)
90 handle (FH h) EOF k = do e <- fEOF h
93implementation Handler FileIO (IOExcept a) where
94 handle () (Open fname m) k = do Right h <- ioe_lift $ openFile fname m
95 | Left err => k False ()
97 handle (FH h) Close k = do ioe_lift $ closeFile h
99 handle (FH h) ReadLine k = do Right str <- ioe_lift $ fGetLine h
100 -- Need proper error handling!
101 | Left err => k "" (FH h)
103 handle (FH h) (WriteString str) k = do Right () <- ioe_lift $ fPutStr h str
104 | Left err => k () (FH h)
106 handle (FH h) EOF k = do e <- ioe_lift $ fEOF h
109-- -------------------------------------------------------------- [ The Effect ]
110FILE_IO : Type -> EFFECT
111FILE_IO t = MkEff t FileIO
113-- ------------------------------------------------------------ [ The Bindings ]
115-- Bind the IO context handlers to functions. These functions will run
119||| Open a file with the specified mode.
121||| @ fname The file name to be opened.
122||| @ m The file mode.
123open : (fname : String)
125 -> Eff Bool [FILE_IO ()]
126 (\res => [FILE_IO (case res of
129open f m = call $ Open f m
133close : Eff () [FILE_IO (OpenFile m)] [FILE_IO ()]
136||| Read a line from the file.
137readLine : Eff String [FILE_IO (OpenFile Read)]
138readLine = call $ ReadLine
140||| Write a string to a file.
141writeString : String -> Eff () [FILE_IO (OpenFile WriteTruncate)]
142writeString str = call $ WriteString str
144||| Write a line to a file.
145writeLine : String -> Eff () [FILE_IO (OpenFile WriteTruncate)]
146writeLine str = call $ WriteString (str ++ "\n")
149eof : Eff Bool [FILE_IO (OpenFile Read)]
152||| Read a complete file, returning a user defined error if
155readFile : (errFunc : String -> e)
157 -> Eff (Either e String) [FILE_IO ()]
158readFile errFunc fname = do
159 case !(open fname Read) of
160 False => pure $ Left (errFunc fname)
166 readAcc : String -> Eff String [FILE_IO (OpenFile Read)]
167 readAcc acc = if (not !(eof))
168 then readAcc (acc ++ !(readLine))
171||| Write a file containing the provided string, returning a user
172||| defined error if unsuccesful.
174writeFile : (errFunc : String -> e)
176 -> (content : String)
177 -> Eff (Either e ()) [FILE_IO ()]
178writeFile errFunc fname content = do
179 case !(open fname WriteTruncate) of
184 False => pure $ Left (errFunc fname)
188 readFile : String -> Eff (Either String String) [FILE_IO ()]
189 readFile = File.readFile id
191 writeFile : String -> String -> Eff (Either String ()) [FILE_IO ()]
192 writeFile = File.writeFile id
193-- --------------------------------------------------------------------- [ EOF ]
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list