
On Sunday 28 January 2007 15:01, Dominic Steinitz wrote:
I've been playing around with streams as a way of implementing cryptographic functions as they seem to allow you to write code that reads more like the specification.
However, I believe (and profiling seems to confirm this) that this builds up a large expression which only gets evaluated at the very end. I naively thought that using lazy bytestrings would solve the problem but the bytestring version just hangs even for small numbers.
So two questions:
1. Are lazy bytestrings the answer but I am using them incorrectly?
2. What techniques are there to force evaluation and throw things that are no longer needed away? And can this be done without losing the spirit of the specification?
Dominic.
module Main(main) where
import Data.Word import Data.Bits import Data.Char import System.Environment
import qualified Data.ByteString.Lazy as BS
-- ByteString version
cbcl iv ps = ciphers where ciphers = 0xff `BS.cons` (BS.pack (BS.zipWith (+) feedIns ciphers)) feedIns = BS.pack (BS.zipWith xor (iv `BS.cons` ciphers) ps)
-- Made up function to illustrate problem
cbc iv ps = ciphers where ciphers = 0xff:(zipWith (+) feedIns ciphers) feedIns = zipWith xor (iv:ciphers) ps
testl n = BS.last (cbcl 0x55 ((BS.pack . take n . repeat . fromIntegral . ord) 'a'))
test :: Int -> Word8 test n = last (cbc 0x55 ((take n . repeat . fromIntegral . ord) 'a'))
main = do progName <- getProgName args <- getArgs if length args /= 1 then putStrLn ("Usage: " ++ progName ++ " <length of string>") else (putStrLn . show . test . read) (args!!0)
Hmmm I've just seen this which may explain why the lazy bytesting version was hanging. But I think my questions are still valid. Dominic. http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-ByteString-L... O(1) cons is analogous to '(:)' for lists. Unlike '(:)' however it is strict in the ByteString that we are consing onto. More precisely, it forces the head and the first chunk. It does this because, for space efficiency, it may coalesce the new byte onto the first 'chunk' rather than starting a new 'chunk'. So that means you can't use a lazy recursive contruction like this: let xs = cons c xs in xs You can however use repeat and cycle to build infinite lazy ByteStrings.