
Hello -- Three related questions, going from most specific to most general : 1 ) Consider the stream processing arrow which computes a running sum, with two implementations : first using generic ArrowCircuits (rSum); second using Automaton (rSum2) : module Foo where import Control.Arrow import Control.Arrow.Operations import Control.Arrow.Transformer import Control.Arrow.Transformer.All rSum :: ArrowCircuit a => a Int Int rSum = proc x -> do rec out <- delay 0 -< out + x returnA -< out rSum2 = Automaton (f 0) where f s n = let s' = s + n in (s', Automaton (f s')) runAuto _ [] = [] runAuto (Automaton f) (x:xs) = let (y, a) = f x in y : runAuto a xs take 10 $ runAuto rSum [1..] [0,1,3,6,10,15,21,28,36,45] take 10 $ runAuto rSum2 [1..] [1,3,6,10,15,21,28,36,45,55] Note that the circuit version starts with the initial value zero. Is there a way to write rSum2 in the general ArrowCircuit form, or using ArrowLoop? 2) Are the ArrowLoop instances for (->), Kleisli Identity, and Kleisli ((->) r) all morally equivalent? (e.g., up to tagging and untagging?) 3) One can define fix in terms of trace and trace in terms of fix. trace f x = fst $ fix (\(m, z) -> f (x, z)) fix f = trace (\(x, y) -> (f y, f y)) undefined Does this mean we can translate arbitrary recursive functions into ArrowLoop equivalents? Best regards, Ben

On Tue, 2010-08-31 at 20:39 -0700, Ben wrote:
Hello --
Three related questions, going from most specific to most general :
1 ) Consider the stream processing arrow which computes a running sum, with two implementations : first using generic ArrowCircuits (rSum); second using Automaton (rSum2) :
module Foo where
import Control.Arrow import Control.Arrow.Operations import Control.Arrow.Transformer import Control.Arrow.Transformer.All
rSum :: ArrowCircuit a => a Int Int rSum = proc x -> do rec out <- delay 0 -< out + x returnA -< out
rSum2 = Automaton (f 0) where f s n = let s' = s + n in (s', Automaton (f s'))
runAuto _ [] = [] runAuto (Automaton f) (x:xs) = let (y, a) = f x in y : runAuto a xs
take 10 $ runAuto rSum [1..] [0,1,3,6,10,15,21,28,36,45]
take 10 $ runAuto rSum2 [1..] [1,3,6,10,15,21,28,36,45,55]
Note that the circuit version starts with the initial value zero.
Is there a way to write rSum2 in the general ArrowCircuit form, or using ArrowLoop?
rSum2 :: ArrowCircuit a => a Int Int rSum2 = proc x -> do rec out <- delay 0 -< out + x returnA -< out + x
2) Are the ArrowLoop instances for (->), Kleisli Identity, and Kleisli ((->) r) all morally equivalent? (e.g., up to tagging and untagging?)
Yes
3) One can define fix in terms of trace and trace in terms of fix.
trace f x = fst $ fix (\(m, z) -> f (x, z)) fix f = trace (\(x, y) -> (f y, f y)) undefined
Does this mean we can translate arbitrary recursive functions into ArrowLoop equivalents?
Yes. In fact fix is used on functional languages that do not support recursion to have recursion (or so I heard)
Best regards, Ben
Regards

Thanks for the prompt reply. Some questions / comments below :
On Wed, Sep 1, 2010 at 12:33 AM, Maciej Piechotka
rSum2 :: ArrowCircuit a => a Int Int rSum2 = proc x -> do rec out <- delay 0 -< out + x returnA -< out + x
Wow, that was simple. I guess I never thought to do this because it evaluates (out + x) twice, but one can always write rSum3 :: ArrowCircuit a => a Int Int rSum3 = proc x -> do rec let next = out + x out <- delay 0 -< next returnA -< next I have a follow-up question which I'll ask in a new thread.
3) One can define fix in terms of trace and trace in terms of fix.
trace f x = fst $ fix (\(m, z) -> f (x, z)) fix f = trace (\(x, y) -> (f y, f y)) undefined
Does this mean we can translate arbitrary recursive functions into ArrowLoop equivalents?
Yes. In fact fix is used on functional languages that do not support recursion to have recursion (or so I heard)
In which case my question is, why is the primitive for Arrows based on trace instead of fix? Best regards, Ben

On Wed, 2010-09-01 at 11:49 -0700, Ben wrote:
Thanks for the prompt reply. Some questions / comments below :
On Wed, Sep 1, 2010 at 12:33 AM, Maciej Piechotka
wrote: rSum2 :: ArrowCircuit a => a Int Int rSum2 = proc x -> do rec out <- delay 0 -< out + x returnA -< out + x
Wow, that was simple. I guess I never thought to do this because it evaluates (out + x) twice, but one can always write
rSum3 :: ArrowCircuit a => a Int Int rSum3 = proc x -> do rec let next = out + x out <- delay 0 -< next returnA -< next
I have a follow-up question which I'll ask in a new thread.
Possibly it should be written as rSum4 :: ArrowCircuit a => a Int Int rSum4 = proc x -> do rec let !next = out + x out <- delay 0 -< next returnA -< next
3) One can define fix in terms of trace and trace in terms of fix.
trace f x = fst $ fix (\(m, z) -> f (x, z)) fix f = trace (\(x, y) -> (f y, f y)) undefined
Does this mean we can translate arbitrary recursive functions into ArrowLoop equivalents?
Yes. In fact fix is used on functional languages that do not support recursion to have recursion (or so I heard)
Ups. Sorry - my dyslexia came to me and I read recursive instead of ArrowLoop. My fault IMHO it is not possible.
In which case my question is, why is the primitive for Arrows based on trace instead of fix?
How would you define loop in terms of fixA :: ArrowLoop a => a b b -> a c b fixA f = loop (second f >>> arr (\(_, x) -> (x, x))) The only way that comes to my mind is: loopA :: (ArrowLoop a, ArrowApply a) => a (b, d) (c, d) -> a b c loopA f = proc (x) -> do arr fst <<< fixA (proc (m, z) -> do f -< (x, z)) -<< x Which requires ArrowApply. So as long as arrow is ArrowLoop and ArrowApply it is possible.
Best regards, Ben
Regards
participants (2)
-
Ben
-
Maciej Piechotka