Let's draw a picture of
bar = ((put' 7) >>> get') &&& get'
to give us an idea of how to write it in arrow notation.
Just as with monadic do
notation, proc
notation introduces named variables, replacing combinators such as >>=
with explicit passing of values.
Anyway, we can see that we need to feed the input, x
, to the two sides, giving:
bar' = proc x -> do
wasput <- put' 7 >>> get' -< x
justgot <- get' -< x
returnA -< (wasput,justgot)
or if we want everything to go from right to left, equivalently
bar'' = proc x -> do
wasput <- get' <<< put' 7 -< x
justgot <- get' -< x
returnA -< (wasput,justgot)
Testing
I'll refactor test
for multiple testing:
test s b = (flip runStateA) s b
So we get
ghci> test bar 3 5
((7,3),3)
ghci> test bar' 3 5
((7,3),3)
ghci> test bar'' 3 5
((7,3),3)
Can we write it without >>>
?
We might be tempted to factor out the (>>>)
:
bar''' = proc x -> do
put7 <- put' 7 -< x
wasput <- get' -< put7
justgot <- get' -< x
returnA -< (wasput,justgot)
oops, no:
ghci> test bar''' 3 5
((3,3),3)
As you pointed out, your state is localised, and the put' 7
doesn't thread through to either get'
, so we haven't managed to get rid of the >>>
or <<<
combinator.
I can't help feeling that's breaking some Arrow law or other. Hmmm...
Broken Arrow law
It took me a while to track down, but after a great deal of hand desugaring and frowning at diagrams, I've found an arrow law staring me in the face that your instance breaks:
first (f >>> g) = first f >>> first g
If we define
dup :: Arrow a => a t (t, t)
dup = arr (\x -> (x,x))
we get
ghci> test (dup >>> (first (put' 7 >>> get'))) 1 3
((7,3),1)
ghci> test (dup >>> (first (put' 7) >>> first get')) 1 3
((1,3),1)
This is because the localised state in put' 7
in the second example doesn't make it into the second first
, if you can follow all those firsts and seconds!
Conclusion:
You found that arrow notation is less useful for your arrow instance because it assumes it's OK to transform via laws that don't hold.
Sadly, whist very interesting indeed, and extraordinarily diverting, it's not a true Arrow.