haskell - 在haskell中从stdin懒惰地读取和操作 float

标签 haskell stdin lazy-evaluation

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

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。

最佳答案

我采取了另一条路线,而是以 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)

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

编辑:我从 chunk 切换过来的至 chunker它使用 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

关于haskell - 在haskell中从stdin懒惰地读取和操作 float ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12514013/

相关文章:

haskell - haskell 中的箭头和函数有何不同?

Haskell 奇异运算符

c - 如何中断另一个标准输入流

go - 在 Go 中扫描向上和向下箭头?

scala - 在 Apache Spark 中,如何使 RDD/DataFrame 操作惰性化?

python - 是否可以使用 mongoengine (python) 延迟查询数据库?

algorithm - 使用 Haskell 查找网格上两点之间的最短路径

arrays - 无法为使用 STUArray 的函数找到合适的签名(GHC 也不能)

python - Python 中的 "stderr"有什么意义?

performance - 如何确定何时对表达式求值?