3

Hey guys, I need some help, how can I sum a list from a file using the sum builtin function?

example: text.txt contains [1,2,3,4]

and i want to get this list from the file and sum these numbers with the sum builtin. Is it possible?

Thanks!

1
  • 1
    See also this FAQ in the haskell+io tag. Commented May 11, 2011 at 22:07

3 Answers 3

3

So, you won't be able to actually get a value :: [Int], because that would be unsafe. But we can get you to IO [Int], and then pass that through >>= into print:

main = (sum . read) `fmap` readFile "myFile" >>= print

If you're using Control.Applicative, you can make it even prettier:

main = sum . read <$> readFile "myFile" >>= print

Voilà! As you can see, this way is much more succinct than using do-notation. do-notation is awesome for getting rid of nested lambdas, but in a lot of cases, it's really not necessary.

Edit: @augustss suggests the following superior alternative:

main = print . sum . read =<< readFile "myFile"

This is awesome, in that it's simpler, and doesn't depend on Control.Applicative; even more importantly, it doesn't have to read be read "inside-out", as @hammar points out.

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

2 Comments

@augustss Wow, that's way better! Thanks.
It also reads better, from right to left, whereas you have to read the applicative one "inside out".
2

Sure.

main = do
    contents <- readFile "text.txt"
    print . sum . read $ contents

This uses some standard functions from the Prelude:

  • readFile :: FilePath -> IO String reads the file into a string.

  • read :: Read a => String -> a converts from a String to any type in the Read typeclass. You might have to add a type annotation if the compiler couldn't figure out which type you wanted. In this case the compiler can figure it out since we used sum on the result, so it infers that a must be [Integer]. (It actually infers Num a => [a], but this defaults to [Integer] due to type defaulting).

    read expects the same format generated by show on the same type.

Note that I had to use do-notation to extract the String from IO String in order to apply read to it.

1 Comment

Technically the compiler guesses which type you wanted (by using a default), since sum can operate on multiple numeric types.
2

If the list is always in this kind of format, you want to use the read function. This function deserializes data, i.e. turns a string into a program data type. For example,

Prelude> read "[1, 2, 3, 4]" :: [Int]
[1,2,3,4]

Now, you can combine this with file IO, but you'll need to read up on Monads if you're not familiar. Some good resources are [ http://www.haskell.org/haskellwiki/Monad ] and Wikipedia. Essentially, each monad will represent a step in a sequential execution -- which is necessary since IO modifies the environment, hence its execution order must be determined.

The code I came up with for reading and then summing is:

main = do
    fc <- readFile "file1"
    parsed <- return (read fc :: [Int])
    putStrLn (printf "sum: %d" (sum parsed))

2 Comments

Thanks, though it's not nice it doesn't understand space delimited numbers without "[" chars around it.
@Alehar if you don't have braces, you can just try the words function, the strip off trailing commas. If you need something more advanced, you might try a Parsec parser.

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.