Thanks for the excellent explanation! : <br><br><div class="gmail_quote">On Fri, Jun 10, 2011 at 4:49 PM, Daniel Fischer <span dir="ltr"><<a href="mailto:daniel.is.fischer@googlemail.com">daniel.is.fischer@googlemail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div class="im">On Friday 10 June 2011, 14:25:59, Dmitri O.Kondratiev wrote:<br>
> Two questions:<br>
> 1) Why to use 'fmap' at all if a complete file is read in a single line<br>
> of text?<br>
<br>
</div>Well, it's a matter of taste whether to write<br>
<br>
foo <- fmap read (readFile "bar")<br>
stuffWithFoo<br>
<br>
or<br>
<br>
text <- readFile "bar"<br>
let foo = read text<br>
stuffWithFoo<br>
<br>
The former saves one line of code (big deal).<br>
<div class="im"><br>
><br>
> 2) Trying to use 'fmap' illustrates 1) producing an error (see below):<br>
> main = do<br>
> let xss = [[1,2,3],[4,5,6],[7,8],[9]]<br>
> writeFile "output.txt" (show xss)<br>
> xss2 <- fmap read (readFile "output.txt") :: [[Int]]<br>
<br>
</div>That type signature doesn't refer to xss2, but to the action to the right<br>
of the "<-", `fmap read (readFile "output.txt")'<br>
<br>
readFile "output.txt" :: IO String<br>
<br>
so<br>
<br>
fmap foo (readFile "output.txt") :: IO bar<br>
<br>
supposing<br>
<br>
foo :: String -> bar<br>
<br>
You want read at the type `String -> [[Int]]', so the signature has to be<br>
<br>
xss2 <- fmap read (readFile "output.txt") :: IO [[Int]]<br>
<div class="im"><br>
> print xss2<br>
><br>
> == Error:<br>
> Couldn't match expected type `[String]'<br>
> with actual type `IO String'<br>
> In the return type of a call of `readFile'<br>
> In the second argument of `fmap', namely `(readFile "output.txt")'<br>
> In a stmt of a 'do' expression:<br>
> xss2 <- fmap read (readFile "output.txt") :: [[Int]]<br>
<br>
</div>Looking at the line<br>
<br>
xss2 <- fmap read someStuff :: [[Int]]<br>
<br>
the compiler sees that<br>
<br>
fmap read someStuff should have type [[Int]]<br>
<br>
Now, fmap :: Functor f => (a -> b) -> f a -> f b<br>
<br>
and [] is a Functor, so the fmap here is map, hence<br>
<br>
map read someStuff :: [[Int]]<br>
<br>
means<br>
<br>
someStuff :: [String]<br>
<br>
That's the expected type of (readFile "output.txt"), but the actual type is<br>
of course IO String, which is the reported error.<br>
</blockquote></div><br><br>