3

I'm rather new to Haskell, and I'm currently using LearnYouAHaskell. I am trying to take a string separated by white space, and break it into a list of smaller word strings. My current program:

main = do 
    putStrLn "Insert a string to convert: "
    -- Input string
    line <- getLine
    words line;

But in this case, it tells me I'm having an IO error. TO my understanding, getLine is an action, and so since this is impure, I have to bind it to "line". Line is an accurate representation of getLine, which is an IO String.

However, shouldn't line be a string? When I try to use words on line, it tells me "Couldn't match expected type "IO a0" with actual type [String]

As if line isn't a string. Furthermore, can I use :t line in the program itself when I make it to see if it's actual of the right type or not?

I apologize for the novice question, but I'm a bit stuck.

EDIT:

I did something similar in GHCI, and it tells me that my type is in fact a normal string.. I don't get it.

Prelude> line <- getLine
"Hello fellows"
Prelude> :t line
line :: String
Prelude> words line
["Hello","fellows"]

Why doesn't that work?

1
  • Explanation of the error: words line has type [String], but all statements in the do block are expected to have type IO a0 for some type a0. Commented Feb 5, 2013 at 22:25

2 Answers 2

7

In haskell if you want to return a value, you have to say so:

main = do 
    putStrLn "Insert a string to convert: "
    -- Input string
    line <- getLine
    return (words line)

words line isn't an IO action, it's a list of strings, so it can't be a statement in a do block.

return :: Monad m => a -> m a and in this case we can specialise it to the type a -> IO a and then to [String] -> IO [String]. Each of the statements in your do block must be IO statements.


Taking it further:

If you want to compile your program, you should have main :: IO(), which means you shouldn't return your list.

If, for example, you wanted to process those strings into a single string then output that, you could do

process :: [String] -> String
process xss = "I don't know, some answer"

main = do 
    putStrLn "Insert a string to convert: "
    -- Input string
    line <- getLine
    putStrLn (process (words line))

although I'd personally write that last line as putStrLn $ process.words $ line.


Your interaction in GHCi

Prelude> line <- getLine
"Hello fellows"
Prelude> :t line
line :: String
Prelude> words line
["Hello","fellows"]

is using the fact that GHCi isn't actually just running in the IO monad. In GHCi, if your input is a valid line in a do block, it'll get run, but if it's pure code it'll get evaluated and printed. (An interactive interpreter like this is often called a REPL for Read-Eval-Print-Loop.)

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your concise explanation!
@Noc You're welcome. Did you see the edit with the info on GHCi? Not so concise now, but hopefully more helpful.
3

Well, the question is what do you want to do with words line?

Having words line as a line inside a do block is doing nothing, but to get it to work you have to use return to wrap it up in the IO monad:

main = do 
    putStrLn "Insert a string to convert: "
    -- Input string
    line <- getLine
    return (words line);

Anyway, perhaps you want to print it instead?

main = do 
    putStrLn "Insert a string to convert: "
    -- Input string
    line <- getLine
    print (words line);

2 Comments

Well, ultimately, the intention is to make a pig Latin converter - it's for homework, but as this isn't something that's purely related to it, I posted it as is. I want to get an input string, use words function to break the string into individual words. Check to see if it begins with a vowel; make a function to check it. Use maps and the pig Latin function, then use unwords to turn it back into a string.
That... And upon further reading, I realized that I had no idea what return did in Haskell. I fell for the disclaimer exactly: "you've done imperative languages like C, Java or Python, you're probably thinking that you know what this return does and chances are you've already skipped this really long paragraph. Well, here's the thing: the return in Haskell is really nothing like the return in most other languages!"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.