2

我是 Haskell 的新手,并试图摆弄一些我在现实世界中经常遇到的测试用例。假设我有包含以下内容的文本文件“foo.txt”:

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 "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"]]
4

5 回答 5

8

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

你可以做什么:

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

这将解包 Bytestring(即,将其转换为字符串)。读取将字符串转换为浮点数。

不确定是否在这里使用字节串甚至有助于您的表现。

于 2009-08-31T20:49:48.363 回答
2

这是1.4.4.3 之前的内部惰性字节串表示类型的指示(在页面中搜索“LPS”)。LPS 是一个构造函数。

于 2009-08-31T20:14:47.403 回答
2

readDatafile 正在返回一个 [[ByteString]],您所看到的是您读取的所有这些字符的“打包”表示。

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"
于 2009-08-31T22:40:26.517 回答
1

这只是惰性字节串构造函数。您尚未将这些字符串解析为整数,因此您将看到底层字符串。请注意,惰性字节串与 String 不同,因此在“Show”n 时它们具有不同的打印表示。

于 2009-09-01T06:56:51.107 回答
1

LPS 是旧的 Lazy ByteString 新类型的旧构造函数。此后它已被显式数据类型替换,因此当前行为略有不同。

当您在 Lazy ByteString 上调用 Show 时,它会打印出代码,该代码将生成与您给它的惰性字节串大致相同的代码。但是,使用 ByteStrings 的通常导入不会导出 LPS——或者在以后的版本中,不会导出 Chunk/Empty 构造函数。因此,它使用 LPS 构造函数来显示它,该构造函数包裹在严格的字节串块列表中,这些块将自己打印为字符串。

另一方面,我想知道惰性 ByteString Show 实例是否应该像大多数其他复杂数据结构的 show 实例一样做同样的事情,并说如下:

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

甚至:

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

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

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

于 2009-09-01T13:44:19.770 回答