3

Back Story: I've been struggling with this problem for the last week now, reading through Learn You A Haskell, and tutorials online, but I can't figure it out.

I've made a lot of progress with understanding list comprehension and recursion, but this one problem is the one thing still standing in my way.

Question: I'm trying to convert a String (or what I think is a String) into a divided list. Here's the code that I have so far (thanks again Jan for the help). It imports the contents of a .txt file.

import System.Environment

main :: IO ()
main = do
     args <- getArgs
     if null args
       then putStrLn "usage: ./pattern dataset.txt"
       else do contents <- readFile $ head args
               putStrLn $ "Filer1: " ++ filterLower(contents)
               convert' contents

filterLower :: String -> String
filterLower st = [ c | c <- st, c `elem` ['A'..'Z']]

I tried making my own convert function:

convert' :: String -> [String]
convert' x = (x:[])

It works, but it doesn't work for this problem.

Any help would be appreciated.

Error: This is the error that I regularly get.

Couldn't match expected type `IO ()' with actual type `[String]'
    In the return type of a call of `convert''
    In the expression: convert' contents
    In the expression:
      do { contents <- readFile $ head args;
             putStrLn $ "-: " ++ filterLower contents;
           convert' contents }
5
  • 3
    What is the error/problem that you run into? Commented Jan 12, 2012 at 17:46
  • I just added my error into the post. Commented Jan 12, 2012 at 18:15
  • What are you expecting to happen after you call convert'? It looks like you're just trying to throw the result away: you don't try to print it or anything. Commented Jan 12, 2012 at 18:22
  • I don't understand what you mean by a "divided string." Commented Jan 12, 2012 at 18:22
  • By "divided string" I mean take something like this "A sentence in quotes" and turn it into something like this ["A", "sentence", "in", "a", "list"]. Commented Jan 12, 2012 at 18:52

3 Answers 3

6

The problem is that the result of convert' is a list of strings, but you're trying to use it as an IO action. You have to do something with the result. For instance,

print $ convert' contents

would print out the result to the screen. Or you could use, e.g. mapM_ putStrLn to print each element out on its own line. Or you could give it a name, and continue writing statements, like:

let converted = convert' contents
...

Going by your comment, it seems that the way you're trying to divide the string is to turn it into a list of its words, e.g. convert' "Hello world"["Hello", "world"]. In that case, you don't need convert' at all — the standard words function does just that! So you can just use words contents and not define convert' at all.

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

2 Comments

I remember Jan telling me about words, but I didn't realize it was a function. But I should have known by now that everything in Haskell is a function. :D I'm back on track now. Thank you for your help.
@SubtleArray, FWIW, it's not true that everything in Haskell is a function. For example, the string "this is not a function" is truthful. Only functions are functions ;-)
5

convert' :: String -> [String], so convert' contents :: [String] is just a list of strings. But you have placed it in an IO-block,

do contents <- readFile whatever
   putStrLn $ ...
   convert' contents

where only expressions of type IO something can appear. There's a simple way to make an IO-less expression into an IO thingy, just return it:

do contents <- readFile ...
   putStrLn $ ...
   return $ convert' contents

is correctly typed. But this do-block has type IO [String], so it doesn't match the declared type of main. How to fix that depends on what you want your programme to do.

1 Comment

I see. It's like a C++ function, limited in functionality by its type. Thank you for the clarification. I'm VERY new to Haskell, and I'm still trying to get around the syntax.
1

I don't understand what you're trying to do here, but the biggest problem is you're not using the do-block correctly. main has type IO (), which implies two constraints:

  • Every "bare" statement (statement without <-) in the do-block must have type IO a for some a.
  • The final statement in the do-block must have type IO (); your final statement has type [String] (and thus the error you're getting). The simplest statement with that type would be return ().

Comments

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.