tags:

views:

469

answers:

6

The show function in Haskell doesn't seem to do what it should:

Prelude> let str = "stack\n\noverflow"
Prelude> putStrLn str
stack


overflow
Prelude> show str
"\"Stack\\n\\n\\noverflow\""
Prelude>

When I declare functions, I normally put the type signatures as Show, which doesn't deal with newlines correctly. I want it to treat \n as newlines, not literally "\n". When I change the type to String, the functions work fine. But I'd have to implement a seperate function for integers, floats, etc, etc.

For example, I may declare a function:

foo :: (Show x) => x -> IO ()
foo x = do
  putStrLn $ show x

... and call it this way:

foo "stack\n\noverflow"
foo 6
foo [1..]

How would I get the function to return what's expected? I.e. which function is similar to show but can return strings containing newlines?

+3  A: 

show show's the variable as you'd have entered it.

Seems pretty regular to me

Alex Gartrell
+6  A: 

The contract of the show method in Haskell is that it produce a string that, when evaluated, yields the value that was shown.

Prelude> let str = "stack\n\noverflow"
Prelude> putStrLn str
stack

overflow
Prelude> putStrLn (show str)
"stack\n\noverflow"
Prelude>
Dave
Just to add to this, the function you described is called "print" which is actually defined just as the above print x = putStrLn (show x)
Phyx
+6  A: 

Sounds like you're trying to simulate a ToString method, although some of your terminology is a little confusing.

You can simulate it like this:

{-# LANGUAGE UndecidableInstances, OverlappingInstances,
             FlexibleInstances, TypeSynonymInstances #-}

class ToString a where
    toString :: a -> String

instance ToString String where
    toString = id

instance Show a => ToString a where
    toString = show

However, as shown by the LANGUAGE pragmas, this is not very desirable. To really get a feel for what you're trying to do it would be easier if we had more context...

Porges
+1  A: 

I'm not really sure the point in what your trying to do. It would help if you clarified a bit. Show is doing what it is supposed to do. Show simply produces a string containing what it was shown.

Rayne
+1  A: 

Porges' plan works and I think it brings out brings out what "show" is really up to, since the confusing behavior you found in ghci will still turn up if you get the IO function you want. (I added an instance for Char to Porges' code, since you would presumably want that not to have quotes.)

{-# LANGUAGE UndecidableInstances, OverlappingInstances,
         FlexibleInstances, TypeSynonymInstances #-}
class ToString a where
  toString :: a -> String

instance ToString String where
  toString = id

instance ToString Char where
  toString x = [x]

instance Show a => ToString a where
  toString = show

foo :: (ToString a) => a -> IO ()
foo x = do {putStrLn $ toString x}

then, in ghci, watch what happens with foo.show :

*Main> let str = "stack\n\noverflow"
*Main> show str
"\"stack\n\noverflow\""
*Main> putStrLn str
stack

overflow
*Main> putStrLn (show str)
"stack\n\noverflow"
*Main> foo str
stack

overflow
*Main> foo (show str)
"stack\n\noverflow"
*Main> foo ( show (show str))
"\"stack\n\noverflow\""
*Main> let newl = "\n"
*Main> foo newl

*Main> putStrLn newl

*Main> putStrLn (show newl)
"\n"

*Main> foo (show newl)
"\n"
*Main> foo (show (show newl))
"\"\n\""
*Main>

+1  A: 

"which function is similar to show but can return strings containing newlines?"

Answer: id

mattiast