A newbie question about Arrows.
Ross Paterson
ross@soi.city.ac.uk
Fri, 10 Jan 2003 12:18:39 +0000
On Thu, Jan 09, 2003 at 10:30:45AM -0600, Shawn P. Garbett wrote:
> On Monday 06 January 2003 04:02 am, Nicolas Oury wrote:
> > I think for example to event-driven arrows : we could make a pair of
> > inputs without mixing the "event happened" information.
>
> Here's one that's been baffling me: What about the case where you have two
> arrows you want to combine. Suppose that each of these arrows are a stream
> processor, which process the type Either.
>
> SP (Either a b) (Either a b)
>
> Now combing these with the sequencing operator is straightforward. The output
> of the first SP becomes the input of the second.
>
> (>>>) :: SP i o -> SP i o -> SP i o
>
> Or in a routing diagram
>
> In >- SP1 --> SP2 --> Out
>
> But what if you wanted to mix up the routing of Left and Right from the
> Either above?
>
> In(Left) -> SP1(Left)
> In(Right) -> SP2(Right)
> SP1(Right) -> SP2(Left)
> SP2(Left) -> SP1(Right)
> SP1(Left) -> Out(Left)
> SP2(Right) -> Out(Right)
Here's a method that's generalizable, if not elegant.
We need a feedback combinator that feeds the Right output channel back
to the input (this is a trivial variant of the loop combinators in the
Fudgets library):
fixSP :: SP a (Either b a) -> SP a b
For convenience we define
output = Left -- produce some output from the network
send = Right -- route to a stream processor
and define a datatype for the components:
data Input a b c d e f
= In (Either a b)
| SP1 (Either c d)
| SP2 (Either e f)
Obviously the need for a new datatype is a drawback, but it lets us name
the components' input streams.
Now your example can be coded in arrow notation as
combine sp1 sp2 = arr In >>> fixSP (proc z -> case z of
In (Left v) ->
returnA -< send (SP1 (Left v))
In (Right v) ->
returnA -< send (SP2 (Right v))
SP1 x -> do
out <- sp1 -< x
returnA -< case out of
Left v -> output (Left v)
Right v -> send (SP2 (Left v))
SP2 x -> do
out <- sp2 -< x
returnA -< case out of
Left v -> send (SP1 (Right v))
Right v -> output (Right v))
Your example had only 1-1 connexions, but the generalization isn't hard.