2009-08-31 139 views
2

我是Haskell的新手,并试图摆弄我通常在现实世界中遇到的一些测试案例。说我有文本文件“foo.txt的”,它包含以下内容:神秘的单词(“LPS”)出现在Haskell输出列表中

45.4 34.3 377.8 
33.2 98.4 456.7 
99.1 44.2 395.3 

我试图产生输出

[[45.4,34.3,377.8],[33.2,98.4,456.7],[99.1,44.2,395.3]] 

我的代码是下面,但我发现了一些假的“ LPS“在输出中...不知道它代表什么。

import qualified Data.ByteString.Lazy.Char8 as BStr 
import qualified Data.Map as Map 

readDatafile = (map (BStr.words) . BStr.lines) 

testFunc path = do 
    contents <- BStr.readFile path 
    print (readDatafile contents) 

testFunc invocated “foo.txt的”输出

[[LPS ["45.4"],LPS ["34.3"],LPS ["377.8"]],[LPS ["33.2"],LPS ["98.4"],LPS ["456.7"]],[LPS ["99.1"],LPS ["44.2"],LPS ["395.3"]]] 

任何帮助表示赞赏!谢谢。 PS:使用ByteString将来会在大量文件中使用。

编辑:

我也困惑的是,为什么输出列表被分组为上述(在[]结合的每个号码)中,当在ghci中下面的线给出了不同的布局研究。

*Main> (map words . lines) "45.4 34.3 377.8\n33.2 98.4 456.7\n99.1 44.2 395.3" 
[["45.4","34.3","377.8"],["33.2","98.4","456.7"],["99.1","44.2","395.3"]] 

回答

8

你看到的确实是一个构造函数。当你读取文件时,结果当然是一串Bytestrings列表,但你想要的是一列Floats列表。

你可以做什么:

readDatafile :: BStr.ByteString -> [[Float]] 
readDatafile = (map ((map (read . BStr.unpack)) . BStr.words)) . BStr.lines 

这拆包字节串(即其转换为字符串)。读取将字符串转换为浮点数。

不知道这里使用bytestrings甚至可以帮助你的表现。

2

这是内部懒惰字节串表示类型pre-1.4.4.3的指示(查询的页为“LPS”)。 LPS是一个构造函数。

+0

是的,我开始认为这与懒惰评估有关。然而,我可以像对待其他任何人一样对待这个列表吗? – jparanich 2009-08-31 20:18:44

+0

我这么认为 - 我的理解是,这只是另一种内部表示,你不应该(大部分)担心。不过,我不太了解Haskell。如果你开始看到不可思议的东西,请不要忘记这一点。 – 2009-08-31 20:22:46

2

readDatafile返回一个[[ByteString]],你看到的是你读取的所有字符的'packed'表示。

readDatafile = map (map Bstr.unpack . bStr.words) . Bstr.lines 

下面是一个示例ghci运行演示问题。我的输出与你的不同,因为我使用GHC 6.10.4:

*Data.ByteString.Lazy.Char8> let myString = "45.4" 
*Data.ByteString.Lazy.Char8> let myByteString = pack "45.4" 
*Data.ByteString.Lazy.Char8> :t myString 
myString :: [Char] 
*Data.ByteString.Lazy.Char8> :t myByteString 
myByteString :: ByteString 
*Data.ByteString.Lazy.Char8> myString 
"45.4" 
*Data.ByteString.Lazy.Char8> myByteString 
Chunk "45.4" Empty 
*Data.ByteString.Lazy.Char8> unpack myByteString 
"45.4" 
+0

感谢Michael的信息......我在链接中注意到Matt Ball在新版本中已经是一个“块”,而不是“LPS [45.4]”,因为它是我的。我敢肯定,哈斯克尔奇才有一个很好的解释,我太新鲜了,无法理解。 :) – jparanich 2009-08-31 22:56:58

1

这只是懒惰的bytestring构造函数。你还没有将这些字符串解析成整数,所以你会看到底层的字符串。请注意,懒惰字节串与String不同,因此当'Show'n时它们具有不同的打印表示形式。

1

LPS是旧的Lazy ByteString newtype的旧构造函数。它已被替换为明确的数据类型,因此当前的行为稍有不同。

当您在Lazy ByteString上调用Show时,它将输出将生成大致相同的惰性字节串的代码。但是,使用ByteStrings的通常导入不会导出LPS - 或在以后的修订版本中导出Chunk/Empty构造函数。所以它用LPS构造函数将其显示为包含严格字节串块的列表,将其自身打印为字符串。

在另一方面,我不知道是否偷懒字节字符串显示实例应该做的,对于复杂的数据结构大多数其他展会情况下做同样的事情,说是这样的:

fromChunks ["foo","bar","baz"] 

甚至:

fromChunks [pack "foo",pack "bar", pack "baz"] 

因为前者似乎依赖{-# LANGUAGE OverloadedStrings #-}使得生成的代码片段可以像Haskell代码一样真正解析。另一方面,打印字符串就好像它们是字符串一样方便。唉,这两个选项都比旧的LPS语法更冗长,但它们比当前的Chunk“Foo”Empty更简洁。最后,Show只需要被Read保留为可逆的,所以它最好不要改变事物,以免它随机破坏大量的序列化数据。 ;)

至于你的问题,你得到一个[[ByteString]]而不是[[Float]]通过映射你的线路上的单词。您需要解压该ByteString,然后在结果字符串上调用read以生成浮点数。