I have these two code snippets, which I'd guess do the same thing, but they don't. Why is that?
This one works fine:
fdup :: String -> IO ()
fdup filename = do
h <- openFile filename ReadMode
c <- hGetContents h
putStr $ unlines $ parse $ lines c
hClose h
This one returns an error Couldn't match expected type ‘IO [String]’ with actual type ‘[String]’
:
fdup' :: String -> IO ()
fdup' filename = do
h <- openFile filename ReadMode
c <- hGetContents h
ls <- lines c
putStr $ unlines $ parse $ ls
hClose h
parse :: [String] -> [String]
What is the difference between them?
As Willem Van Onsem explained, you don't need <-
in that specific place because lines c
is just a list of strings, and not an IO
computation. If you want to give it a name, you can use a let-binding instead:
fdup' :: String -> IO ()
fdup' filename = do
h <- openFile filename ReadMode
c <- hGetContents h
let ls = lines c
putStr $ unlines $ parse $ ls
hClose h