Lazy to read and manipulate stdin float in haskell

I am trying to read data as doubled from stdin, manipulate them and write them as well. So far I have come to the following:

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 

The idea is to bind data to a program, which is then transmitted through a feedback system before it is written to standard output. Although now it just prints the first 10 values.

It works, but does not seem lazy. Ie he has to read all the memory input. So:

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

will work fine, but:

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

will not be. I assume this is a listOfFloat64le function that makes things work incorrectly. So, how do I create iterability to go into my sys function without having to read everything in memory?

I am not a very experienced haskeller.

+4
source share
3 answers

I made another route, instead dividing the ByteString at 8-byte intervals and translating it to it instead:

 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) 

It seems to work at least, but I don't know what performance is.

EDIT: I switched from chunk to chunker , which uses runGetState instead:

 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 

And using it like: let signal = chunker getFloat64le input

+1
source

See this question . It seems that Binary has become more rigorous than it was a long time ago when I used it.

0
source

This seems like a standards issue where you can easily use something like pipes or conduits . You can make stdin as the source and stdout as the receiver and apply the transformer as conduit .

0
source

Source: https://habr.com/ru/post/1435281/


All Articles