简体   繁体   中英

Haskell String to List of Strings using Words

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?

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 -> ma 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.)

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM