How to Check whether a file exists and IO[String] vs [String]

Jon Cast jcast@ou.edu
Fri, 02 May 2003 16:56:17 -0500


Alexandre Weffort Thenorio <alethenorio@home.se> wrote:

> Hello. I am having two problems. I have a program that reads two texts
> file and writes a new text with its info. So I have done so that if
> main file doesn't exist I just output an error string but my problem
> is when it comes to the second file. This file is not exactly needed
> so if it is not there, the program should just ignore the file. I
> tried doing that but if the second file is there I also get an error
> saying that it couldn;t find the file. So is it possible to check
> whether a file exists

Yes.  See Directory.doesFileExist.

> or not outputting and empty string if not or the actual data from it
> if so without giving an error and making the program not run??
> 
> For example
> 
> main = do
>   mainfile <- readFile "xxxxx.txt"
>   secondfile <- readMyFile "yyyy.txt"
>   writeFile "test.txt" mainfile++secondfile
> 
> 
> readMyFile file = do
>  list <- readFile file
>  if list == "" then return "" else return list
>
> Apparently this doesn't work and if file doesn't exist it still gives
> me an error.

Correct.  readFile always assumes the file exists (not to mention, if
list == "", then list = "", so we can calculate:

  readMyFile file
= do list <- readFile file
     if list == "" then return "" else return list
= do list <- readFile file
     if list == "" then return list else return list
= do list <- readFile file
     return list
= readFile file

so your readMyFile function as written is unnecessary.)

If you want to take a different action if the file doesn't exists you
have to use doesFileExist as above.

> Another problem I ran into is with IO[String] and [String].
> 
> I have a function like
> 
> foo = do
>  nf <- readFile "xxx.txt"
>  return (lines nf)
> 
> Then when I try using foo like a [String] in other programs I run into
> type error.

True.  IO a /= a; they're not even isomorphic.

> How can I turn this IO[String] into a [String] so I don't actually
> have to open this file in the main and then use it as an argument of
> another function running "lines' on main method????

If you want to pass the result into f, you can say:

do
  x <- foo
  return (f x)

or fmap f foo.

Jon Cast