
ChrisK wrote:
Could I has one question? What is the purpose of the "stream" function in the ArrowLoop instance? Is it just to catch an unexpected [] at runtime?
instance ArrowLoop SF where loop (SF f) = SF $ \as -> let (bs,cs) = unzip (f (zip as (stream cs))) in bs where stream ~(x:xs) = x:stream xs
It looks like stream is (almost) an identity which would crash at runtime if it encountered a []. In particular it is equivalent to
where stream xs = head xs:stream (tail xs)
Not quite that, from a blog post of mine a while back: [snip] But then the trouble arrived - I suddenly noticed that the paper was using infinite sequences, not the finite sequences I was using myself. Trying to implement an ArrowLoop as per the paper led to horrible grief: -- instance ArrowLoop SF where -- loop (SF f) = SF (loop (unzip . f . uncurry zip)) The problem is that this is far too strict - on non-empty input it caused stack overflow crashes, which isn't exactly what I wanted. I found the solution in Programming With Arrows [1] (page 17), which involves some subtlety with lazy patterns: instance ArrowLoop SF where loop (SF f) = SF $ \as -> let (bs,cs) = unzip (f (zip as (stream cs))) in bs where stream ~(x:xs) = x:stream xs [unsnip] http://www.haskell.org/arrows/biblio.html#Hug05 [1] Hope this helps, Claude -- http://claudiusmaximus.goto10.org