summaryrefslogtreecommitdiff
path: root/fp2/week2/camil/StdIOMonad.icl
blob: c25cb4cece1929c18475815bc158c6a81c8e242e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
implementation module StdIOMonad

import StdBool
import StdEnum
import StdFile
import StdList
import StdMaybe
import StdMisc
import StdMonad
import StdOverloaded
import StdString
import StdTuple

:: IO a = IO (*W -> *(a, *W))
:: *W :== *(*World, *[*(Filehandle, *File)])
:: Filemode = Lees | Schrijf
:: Filenaam :== String
:: Filehandle :== String

instance toInt Filemode where
	toInt Lees = FReadText
	toInt Schrijf = FWriteText

//voer monadische I/O actie uit op de wereld:
doIO:: (IO a) *World -> *(a, *W)
doIO (IO f) w = f (w, [])

unIO:: (IO a) -> *W -> *(a, *W)
unIO (IO f) = f 

//  IO is een monad:
instance return IO where
	return x = IO (\w -> (x, w))
instance >>=    IO where
	(>>=) (IO f) g = IO (\w = let (a, w1) = f w in unIO (g a) w1)

read:: IO String
read = IO read`
	where
		read`:: *W -> *(String, *W)
		read` (world, s)
		# (io, world) = stdio world
		# (line, io) = freadline io
		# (_, world) = fclose io world
		= (line, (world, s))

//	schrijf regel naar de console:
write		:: String -> IO Void
write s = IO (write` s)
	where
		write`:: String *W -> *(Void, *W)
		write` line (world, s)
		# (io, world) = stdio world
		# io = io <<< line
		# (_, world) = fclose io world
		= (Void, (world, s))

//	open de file met gegeven filenaam en mode:
find:: Filehandle *[*(Filehandle, *File)] -> (Maybe *(Filehandle, *File), *[*(Filehandle, *File)]) 
find fh fs
# (fhs, fis) = unzip fs
# fhsC = zip2 [0..length fhs] fhs
# index = [(i, h) \\ (i, h) <- fhsC | h == fh]
| length index == 0 = (Nothing, zip2 fhs fis)
# index = fst (hd index)
# (fis1, fis2) = splitAt index fis
# (fhs1, fhs2) = splitAt index fhs
# (thefile, fis2) = splitAt 1 fis2
# (thehandle, fhs2) = splitAt 1 fhs2
= (Just (hd thehandle, hd thefile), zip2 (fhs1 ++ fhs2) (fis1 ++ fis2))


open:: Filenaam Filemode -> IO (Maybe Filehandle)
open s m = IO (open` s m)
	where
		open`:: String Filemode *W -> *(Maybe Filehandle, *W)
		open` fp m (world, fs)
		| any (\l = fp == fst l) fs = (Nothing, (world, fs))
		# (ok, file, world) = fopen fp (toInt m) world
		= (Just fp, (world, [(fp, file):fs]))

//	sluit de file met gegeven filenaam:
close:: Filehandle -> IO Bool
close fh = IO (close` fh)
	where
		close`:: Filehandle *W -> *(Bool, *W)
		close` fp (world, fs)
		# (currentfiletuple, fs) = find fp fs
		| isNothing currentfiletuple = (False, (world, fs))
		# (currentfh, currentfile) = fromJust currentfiletuple
		# (ok, world) = fclose currentfile world
		| not ok = abort "File can't be closed"
		| otherwise = (True, (world, fs))
		

//	bepaal of het lezen van de file klaar is:
eof			:: Filehandle -> IO Bool
eof fh = IO (eof` fh)
	where 
		eof`:: Filehandle *W -> *(Bool, *W)
		eof` fp (world, fs)
		# (currentfiletuple, fs) = find fp fs
		| isNothing currentfiletuple = abort "Can't do eof on non-existing file"
		# (currentfh, currentfile) = fromJust currentfiletuple
		# (ok, file) = fend currentfile
		= (ok, (world, [(currentfh, file):fs]))

//	lees een regel van een file:
readline	:: Filehandle -> IO (Maybe String)
readline fh = IO (readline` fh)
	where
		readline` :: Filehandle *W -> *(Maybe String, *W)
		readline` fh (world, fs)
		# (currentfiletuple, fs) = find fh fs
		| isNothing currentfiletuple = (Nothing, (world, fs))
		# (currentfh, currentfile) = fromJust currentfiletuple
		# (s, currentfile) = freadline currentfile
		= (Just s, (world, [(currentfh, currentfile):fs]))

//	schrijf een regel naar een file:
writeline	:: String Filehandle -> IO Bool
writeline s fh = IO (writeline` s fh)
	where
		writeline` :: String Filehandle *W -> *(Bool, *W)
		writeline` s fh (world, fs)
		# (currentfiletuple, fs) = find fh fs
		| isNothing currentfiletuple = (True, (world, fs))
		# (currentfh, currentfile) = fromJust currentfiletuple
		# currentfile = fwrites (s +++ "\n") currentfile
		= (True, (world, [(currentfh, currentfile):fs]))