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が解凍されます(つまり、文字列に変換されます)。読み取りは文字列をfloatに変換します。

ただし、ここでバイト文字列を使用することでパフォーマンスが向上するかどうかはわかりません。

于 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は、古いLazyByteStringnewtypeの古いコンストラクターでした。その後、明示的なデータ型に置き換えられたため、現在の動作は少し異なります。

レイジーバイトストリングで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 に答える