tags:

views:

166

answers:

2

is there a difference like that from IO String to String

i want to take some String values from a IO.

can anyone tell me about this issue. im clueless

+4  A: 

An IO String is a String in the IO-Monad. If a function in the IO-Monad returns an IO String, you get the String by doing:

do str <- ioFunc

A function is in the IO-Monad when it needs IO-access and has to return IO types.

stefaanv
+2  A: 

The question is what you want to do with the String value that your IO String action is going to result in, when the program is run. You write as if you already have your hands on the string, but you don't.

Or: you write as if you have defined or isolated a string, but you haven't. So far you have defined or isolated an action that returns a string. Individual cases of performing that action will return different strings.

Presumably you are trying to define a more complex action -- something of type IO Blah -- maybe something of type IO () the type of something that can be compiled to an executable. The idea is that in the more complex action, having arrived a String value by performing an action of the type IO String -- the action you've so far defined -- the executor of the complex action will go on to do something that depends on just what that value is. This is something represented by a function of the type String -> IO Blah -- maybe String -> IO ()

Of course, such a function doesn't take IO String values (i.e. actions that return strings) as arguments, but String values as arguments. We cannot join them directly.

To get from your action that returns a string -- your IO String value -- and a 'String -> IO Blah' function, to something new -- an action that returns a blah -- we join them through the function >>=. Specialized to this case >>= has the type IO String -> (String -> IO Blah) -> IO Blah -- it might be IO String -> (String -> IO ()) -> IO ()

So, to take the most trivial example of a pair of such things, consider getLine and putStrLn.

getLine is the action of finding out what string has just been entered -- it has the type IO String.

You might say that putStrLn prints a String value to the screen and then returns to the left margin. But that's superficial: what definite thing is done depends on the specification of a String value, so it has the type String -> IO(). Which is to say: putStrLn doesn't do anything, it is a function that maps strings to things that can be done. So as usual, you can define a value in its range type (actions, i.e. IO () 's) by following the function sign with a name of something in the domain type (strings, i.e. String) So the combination putStrLn "Gee whiz" names a definite action, something of type IO ().

ghci will perform such actions on the fly, so, for any string like "Gee whiz" you can write putStrLn "Gee whiz" and it will immediately 'perform this action' -- the action of writing "Gee whiz" to the screen and returning to the left margin.

Prelude> putStrLn "Gee whiz"
Gee whiz
Prelude> 

Similarly the one-character string, that just has the Unix bell character \BEl in it, is the string we name with '\BEl':[] or ['\BEL'] or "\BEL". For that string as argument, putStrLn has an audibly quite different kind of action for a value. We get

Prelude> putStrLn "\BEL"

Prelude> 

Here you will hear the Unix bell ring before it returns to the left margin. It's a pretty lame audio program, but there you are. ghci is performing the action of sounding the Unix bell, the action you named with the words putStrLn "\BEL" before pressing return.

So anyway getLine is a value of type IO String and you want to "take this String value from IO". Of course, it doesn't exist yet, it depends what the user types. But we can consider what the program is to do with such a value when it gets it. We can specify this by specifying a function from strings to actions, like putStrLn. We can thus define a complete action that 'takes a value' and uses it in a certain way by composing them with >>= or the do notation sugar.

The most trivial case would be something like echo:

echo :: IO ()
echo = getLine >>= putStrLn

or equivalently

echo = getLine >>= (\x -> putStrLn x)

or in do notation:

echo = do 
     the_string_i_want_to_take <- getLine
     putStrLn the_string_i_want_to_take

or less absurdly:

echo = do 
     x <- getLine
     putStrLn x

Of course, you want to "take the string" and maybe mess with it before finishing.

reverseEcho :: IO ()
reverseEcho = getLine >>= (\x -> putStrLn (reverse x))

or more compactly:

reverseEcho = getLine >>= (putStrLn . reverse)

or in do notation:

reverseEcho = do 
        the_string_i_want_to_take <- getLine
        putStrLn (reverse the_string_i_want_to_take)

or less absurdly:

reverseEcho = do 
        x <- getLine
        putStrLn (reverse  x)

if you want to think of 'reversing the string' as something that is done with the string in between getting and printing, you could write:

reverseEcho = do 
        the_string_i_want_to_take <- getLine
        the_string_after_i_have_processed_it <- return (reverse the_string_i_want_to_take)
        putStrLn (the_string_after_i_have_processed_it)

or

reverseEcho = do
        x <- getLine
        y <- return x
        putStrLn y

or equivalently

reverseEcho = (getLine >>= (return . reverse)) >>= putStrLn 

Here the parentheses aren't necessary because the precedence levels for . and >>= are suitably optimized. But (getLine >>= (return . reverse)) is just another name of an "action that returns a string", a value of IO String, which is not a string itself. You cant apply a String -> Whatever function to it directly to get a Whatever, but you can combine it with a function from strings to actions via >>=.

Similarly

reverseFileAA :: IO ()
reverseFileAA = readFile "AA.txt" >>= writeFile "reversedAA.txt" . reverse

is the action of writing a file named "reversedAA.txt" with the reverse of the string found in AA.txt, whatever it is, and might be written

reverseFileAA = do
     old_file_contents <- readFile "AA.txt"
     new_file_contents <- return (reverse old_file_contents)
     writeFile "reversedAA.txt" old_file_contents
Arthur