As you might have noticed, the error message is telling you there's problem with read, so let's focus on that.
As I said in comments, read takes a string representation of a value of some data type, tries to parse it and return that value. Some examples:
read "3.14" :: Double ≡ 3.14 :: Double
read "'a'" :: Char ≡ 'a' :: Char
read "[1,2,3]" :: [Int] ≡ [1,2,3] :: [Int]
Some nonexamples:
read "[1,2," :: [Int] ≡ error "*** Exception: Prelude.read: no parse"
read "abc" :: Int ≡ error "*** Exception: Prelude.read: no parse"
What happens when you try to use String version of read (i.e. read :: String → String)?
Haskell's representation of String (e.g. when you evaluate something that returns String in GHCi) consists of series of characters enclosed in " ... " quotes. Of course, if you want to show some special character (like newline), you have to put the escaped version in there (\n in this case).
Remember when I wrote that read expects a string representation of a value? In your case, read expects exactly this string format. Naturally, the first thing it tries to do is to match the opening quote. Since your first line doesn't begin with ", read complains and crashes the program.
read "hello" :: String fails in the same way that read "1" :: [Int] fails; 1 alone cannot be parsed as list of Ints - read expects the string to start with opening bracket [.
You might have also heard of show, which is the inverse (but in very loose sense) to read. As a rule of thumb, if you want to read a value x, the string representation read expects looks like show x.
If you were to change the content of the file to following
"this is line one"
"another line"
"and the final line"
your code would work just fine and produce following input:
["this is line one","another line","and the final line"]
If you don't want to change your .txt file, just remove list = listLines myLines and do print myLines. However, when you run the program, you'll get
["this is line one","another line","and the final line"]
again. So what's the issue?
print = putStrLn ∘ show and the default behaviour of show when it comes to showing list of something (i.e. [a] for some a; with exception of Char, which gets special treatment) is to produce string [ firstElement , secondElement ... lastElement ]. As you can see, if you want to avoid the [ ... ], you have to merge [String] back together.
There's nifty function called unlines, which is the inverse of lines. Also note, that print calls show first, but we do not want that in this case (we got the string we wanted already)! So we use putStrLn and we're done. Final version:
main = do
handle <- openFile "data.txt" ReadMode
contents <- hGetContents handle
let myLines = lines contents
putStrLn (unlines myLines)
hClose handle
We could also get rid of the unneeded lines ~ unlines and just putStrLn contents.