简体   繁体   English

Haskell IO字符串->列表

[英]Haskell IO String -> List

Hey guys, I need some help, how can I sum a list from a file using the sum builtin function? 大家好,我需要一些帮助,如何使用内建的sum函数对文件列表进行求和?

example: text.txt contains [1,2,3,4] 例如:text.txt包含[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. 因此,您将无法实际获得值:: [Int] ,因为那是不安全的。 But we can get you to IO [Int] , and then pass that through >>= into print : 但是我们可以将您带到IO [Int] ,然后将其通过>>=传递给print

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

If you're using Control.Applicative , you can make it even prettier: 如果您使用Control.Applicative ,则可以使其更漂亮:

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

Voilà! 瞧! As you can see, this way is much more succinct than using do -notation. 如您所见,这种方式比使用do -notation简洁得多。 do -notation is awesome for getting rid of nested lambdas, but in a lot of cases, it's really not necessary. do notation对于消除嵌套的lambda很棒,但是在很多情况下,这实际上不是必需的。

Edit: @augustss suggests the following superior alternative: 编辑: @augustss建议以下替代方法:

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

This is awesome, in that it's simpler, and doesn't depend on Control.Applicative ; 这很棒,因为它更简单,并且不依赖于Control.Applicative ; even more importantly, it doesn't have to read be read "inside-out", as @hammar points out. 更重要的是, @ hammar指出,它不必读成“由内而外”。

Sure. 当然。

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

This uses some standard functions from the Prelude: 这使用了Prelude中的一些标准功能:

  • readFile :: FilePath -> IO String reads the file into a string. readFile :: FilePath -> IO String将文件读取为字符串。

  • read :: Read a => String -> a converts from a String to any type in the Read typeclass. read :: Read a => String -> aString转换为Read类型类中的任何类型。 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] . 在这种情况下,由于我们在结果上使用了sum ,因此编译器可以弄清楚,因此它推断a必须为[Integer] (It actually infers Num a => [a] , but this defaults to [Integer] due to type defaulting). (它实际上推断Num a => [a] ,但是由于类型默认值,它默认为[Integer] )。

    read expects the same format generated by show on the same type. read期望使用相同类型的show生成相同的格式。

Note that I had to use do-notation to extract the String from IO String in order to apply read to it. 请注意,我不得不用做标记法提取StringIO String才能申请read它。

If the list is always in this kind of format, you want to use the read function. 如果列表始终采用这种格式,则要使用read功能。 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. 现在,您可以将其与文件IO结合使用,但是如果您不熟悉,则需要阅读Monad。 Some good resources are [ http://www.haskell.org/haskellwiki/Monad ] and Wikipedia. 一些很好的资源是[ http://www.haskell.org/haskellwiki/Monad ]和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. 本质上,每个monad将代表顺序执行中的一个步骤-由于IO会修改环境,因此这是必需的,因此必须确定其执行顺序。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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