简体   繁体   中英

Haskell IO String -> List

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!

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.

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.

If the list is always in this kind of format, you want to use the read function. This function deserializes data, ie 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))

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