2008/12/7 John Ky <newhoggy@gmail.com>
Thanks for the clarification.

They're all the same, as you've explained:

Prelude> putStrLn $ (show . read) "123"
*** Exception: Prelude.read: no parse

The "no parse" is an artifact of defaulting:

Prelude> putstrLn $ (show . read) "()"
()

It's because ghci defaults the free type variables to ().  
 
The signatures for show and read are:

show :: (Show a) => a -> String
read :: (Read a) => String -> a

So when you do show . read, you get String -> String, but where did the a's go?  What type were they (what type is "read" trying to parse)?  Ghci makes them (), because it's weird like that.  A compiler will complain that there is an unconstrained type variable that it doesn't know what to do with.

You can constrain it yourself with something like:

showAs :: (Show a) => a -> a -> String
showAs typ x = show (x `asTypeOf` typ)

Then:

Prelude> putStrLn $ (showAs (undefined::Int) . read) "123"
123

But this situation doesn't arise in practice, because usually you do something with a value you've read other than just printing it, and that something will determine the type to read.

Luke