1. The Easy Part
  2. Higher Order Functions
  3. Types
  4. Lists
  5. Complex Data Objects
  6. File IO
  7. Classes
  8. Monads
  9. List Monads
  10. Shared Transactional Memory

File IO

Reading a Whole File

rdf.hs
1main = do
2    line <- readFile "/etc/group"
3    putStrLn line
$ ghc --make rdf.hs
[1 of 1] Compiling Main             ( rdf.hs, rdf.o )
Linking rdf ...
$ ./rdf
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,adm
adm:x:4:root,adm,daemon
tty:x:5:
disk:x:6:root
lp:x:7:daemon,lp
mem:x:8:
kmem:x:9:
wheel:x:10:root
mail:x:12:mail
news:x:13:news
uucp:x:14:uucp
man:x:15:
games:x:20:
gopher:x:30:
dip:x:40:
ftp:x:50:
lock:x:54:
nobody:x:99:
users:x:100:
utmp:x:22:
utempter:x:35:
floppy:x:19:
vcsa:x:69:
nscd:x:28:
slocate:x:21:
tcpdump:x:72:
gnokii:x:499:
dbus:x:81:
polkituser:x:87:
pulse:x:498:
pulse-rt:x:497:
pulse-access:x:496:
smolt:x:495:
rpcuser:x:29:
nfsnobody:x:494:
avahi:x:493:
wbpriv:x:88:
openvpn:x:492:
apache:x:48:
mailnull:x:47:
smmsp:x:51:
sshd:x:74:
haldaemon:x:68:
ntp:x:38:
gdm:x:42:
sbrandt:x:500:
jackuser:x:491:
hsqldb:x:96:
ubiqis:x:490:
postgres:x:26:
tomcat:x:91:
gold:x:489:
amie:x:488:
tgcdb:x:487:
torrent:x:486:
avahi-autoipd:x:485:
screen:x:84:
mysql:x:27:
rpc:x:32:


Reading a File Line by Line

rdf2.hs
1import System.IO
2 
3doline fh = do
4    line <- hGetLine fh
5    putStrLn line
6    prlines fh
7 
8prlines fh = do
9    eof <- hIsEOF fh
10    case eof of
11        True -> putStr ""
12        False -> doline fh
13 
14main = do
15    fh <- openFile "/etc/group" ReadMode
16    prlines fh
17    hClose fh
$ ghc --make rdf2.hs
[1 of 1] Compiling Main             ( rdf2.hs, rdf2.o )
Linking rdf2 ...
$ ./rdf2
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,adm
adm:x:4:root,adm,daemon
tty:x:5:
disk:x:6:root
lp:x:7:daemon,lp
mem:x:8:
kmem:x:9:
wheel:x:10:root
mail:x:12:mail
news:x:13:news
uucp:x:14:uucp
man:x:15:
games:x:20:
gopher:x:30:
dip:x:40:
ftp:x:50:
lock:x:54:
nobody:x:99:
users:x:100:
utmp:x:22:
utempter:x:35:
floppy:x:19:
vcsa:x:69:
nscd:x:28:
slocate:x:21:
tcpdump:x:72:
gnokii:x:499:
dbus:x:81:
polkituser:x:87:
pulse:x:498:
pulse-rt:x:497:
pulse-access:x:496:
smolt:x:495:
rpcuser:x:29:
nfsnobody:x:494:
avahi:x:493:
wbpriv:x:88:
openvpn:x:492:
apache:x:48:
mailnull:x:47:
smmsp:x:51:
sshd:x:74:
haldaemon:x:68:
ntp:x:38:
gdm:x:42:
sbrandt:x:500:
jackuser:x:491:
hsqldb:x:96:
ubiqis:x:490:
postgres:x:26:
tomcat:x:91:
gold:x:489:
amie:x:488:
tgcdb:x:487:
torrent:x:486:
avahi-autoipd:x:485:
screen:x:84:
mysql:x:27:
rpc:x:32:

See http://cgi.cse.unsw.edu.au/~dons/blog/2006/12/17.

The problem with this approach is that it betrays an imperative way of thinking. Possibly the programmer was worried that readFile, because it returns the entire contents of a file as a string, was wasting memory. Not so. Haskell is smart enough to only read as much of the file as it needs to.


Read a File Line by Line, Again

rdfs3.hs
1-- Split up a string into an array, using character c as a delimiter
2split _ [] = []
3split c str =
4    (takeWhile (c /= ) str) : (split c (drop 1 (dropWhile (c /=) str)))
5 
6-- Print out lines one by one
7prlines [] = putStr ""
8prlines (a:b) = do
9    putStrLn a
10    prlines b
11 
12main = do
13    file <- readFile "/etc/group"
14    prlines(split '\n' file)
$ ghc --make rdfs3.hs
[1 of 1] Compiling Main             ( rdfs3.hs, rdfs3.o )
Linking rdfs3 ...
$ ./rdfs3
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,adm
adm:x:4:root,adm,daemon
tty:x:5:
disk:x:6:root
lp:x:7:daemon,lp
mem:x:8:
kmem:x:9:
wheel:x:10:root
mail:x:12:mail
news:x:13:news
uucp:x:14:uucp
man:x:15:
games:x:20:
gopher:x:30:
dip:x:40:
ftp:x:50:
lock:x:54:
nobody:x:99:
users:x:100:
utmp:x:22:
utempter:x:35:
floppy:x:19:
vcsa:x:69:
nscd:x:28:
slocate:x:21:
tcpdump:x:72:
gnokii:x:499:
dbus:x:81:
polkituser:x:87:
pulse:x:498:
pulse-rt:x:497:
pulse-access:x:496:
smolt:x:495:
rpcuser:x:29:
nfsnobody:x:494:
avahi:x:493:
wbpriv:x:88:
openvpn:x:492:
apache:x:48:
mailnull:x:47:
smmsp:x:51:
sshd:x:74:
haldaemon:x:68:
ntp:x:38:
gdm:x:42:
sbrandt:x:500:
jackuser:x:491:
hsqldb:x:96:
ubiqis:x:490:
postgres:x:26:
tomcat:x:91:
gold:x:489:
amie:x:488:
tgcdb:x:487:
torrent:x:486:
avahi-autoipd:x:485:
screen:x:84:
mysql:x:27:
rpc:x:32: