4

我正在尝试从标准输入读取数据作为双精度,操作它们并写入它们。到目前为止,我想出的是:

import qualified Data.ByteString.Lazy as B
import Data.Binary.IEEE754
import Data.Binary.Get

-- gives a list of doubles read from stdin
listOfFloat64le = do
  empty <- isEmpty
  if empty
     then return []
     else do v <- getFloat64le
             rest <- listOfFloat64le
             return (v : rest)


-- delay signal by one
delay us = 0 : us

-- feedback system, add delayed version of signal to signal
sys us = zipWith (+) us (delay us)

main = do
    input <- B.getContents
    let hs = sys $ runGet listOfFloat64le input
    print $ take 10 hs

这个想法是将数据馈送到程序中,然后在将其写入标准输出之前通过反馈系统。虽然现在它只打印前 10 个值。

这有效,但似乎并没有懒惰地评估。即它必须将所有输入读入内存。所以:

dd if=/dev/urandom bs=8 count=10 | runhaskell feedback.hs

会很好,但是:

dd if=/dev/urandom | runhaskell feedback.hs

将不会。我的猜测是它listOfFloat64le使事情无法正常工作的功能。那么如何创建一个可迭代的对象来传递给我的sys函数,而不必将所有内容都读入内存呢?

我不是一个很有经验的haskeller。

4

3 回答 3

1

我采取了另一条路线,而是以 8 个字节的间隔拆分 ByteString 并对其进行映射:

import qualified Data.ByteString.Lazy as L
import Data.Binary.IEEE754
import Data.Binary.Get

-- delay signal by one
delay us = 0 : us

-- feedback system, add delayed version of signal to signal
sys us = zipWith (+) us (delay us)

-- split ByteString into chunks of size n
chunk n xs = if (L.null xs)
        then []
        else y1 : chunk n y2
          where
            (y1, y2) = L.splitAt n xs


main = do
    input <- L.getContents

    let signal = map (runGet getFloat64le) (chunk 8 input)
    print $ take 10 (sys signal)

这似乎至少有效,但我不知道性能如何。

编辑:我切换chunkchunker使用 runGetState 代替:

chunker :: Get a -> L.ByteString -> [a]
chunker f input = if (L.null input)
                     then []
                     else val : chunker f rest
                       where
                        (val, rest, _) = runGetState f input 0

并像这样使用它:let signal = chunker getFloat64le input

于 2012-09-20T15:52:46.200 回答
0

这似乎是一个标准问题,您可以轻松地使用类似pipesor的东西conduits。您可以将stdin其作为源和stdout接收器,并将变压器应用为conduit.

于 2012-09-20T17:07:19.133 回答
0

看到这个问题。看起来 Binary 比我很久以前使用它时变得更严格了。

于 2012-09-20T14:45:06.610 回答