[Haskell-cafe] Data.List / Map: simple serialization?

Daniel Fischer daniel.is.fischer at googlemail.com
Fri Jun 10 14:49:57 CEST 2011


On Friday 10 June 2011, 14:25:59, Dmitri O.Kondratiev wrote: 
> Two questions:
> 1) Why to use 'fmap' at all if a complete file is read in a single line
> of text?

Well, it's a matter of taste whether to write

    foo <- fmap read (readFile "bar")
    stuffWithFoo

or

    text <- readFile "bar"
    let foo = read text
    stuffWithFoo

The former saves one line of code (big deal).

> 
> 2) Trying to use 'fmap' illustrates 1) producing an error (see below):
> main = do
>      let xss = [[1,2,3],[4,5,6],[7,8],[9]]
>      writeFile "output.txt" (show xss)
>      xss2 <- fmap read (readFile "output.txt") :: [[Int]]

That type signature doesn't refer to xss2, but to the action to the right 
of the "<-", `fmap read (readFile "output.txt")'

readFile "output.txt" :: IO String

so

fmap foo (readFile "output.txt") :: IO bar

supposing

foo :: String -> bar

You want read at the type `String -> [[Int]]', so the signature has to be

    xss2 <- fmap read (readFile "output.txt") :: IO [[Int]]

>      print xss2
> 
> == Error:
>  Couldn't match expected type `[String]'
>              with actual type `IO String'
>  In the return type of a call of `readFile'
>  In the second argument of `fmap', namely `(readFile "output.txt")'
>  In a stmt of a 'do' expression:
>      xss2 <- fmap read (readFile "output.txt") :: [[Int]]

Looking at the line

    xss2 <- fmap read someStuff :: [[Int]]

the compiler sees that

fmap read someStuff should have type [[Int]]

Now, fmap :: Functor f => (a -> b) -> f a -> f b

and [] is a Functor, so the fmap here is map, hence

map read someStuff :: [[Int]]

means

someStuff :: [String]

That's the expected type of (readFile "output.txt"), but the actual type is 
of course IO String, which is the reported error.



More information about the Haskell-Cafe mailing list