Question about implementation of an "information-passnig" arrow

Brandon Michael Moore brandon at its.caltech.edu
Tue Sep 16 09:40:39 EDT 2003



On Mon, 15 Sep 2003, Yu Di wrote:

> data MyArrow a b = MyArrow ((String, a) -> (String,
> b))
>
> i.e. there is an "information" asscioated with each
> piece of data (represented by the string), and I want
> to pass it around. And often the arrow's processing
> logic will depend on the input information, therefore
> a monad-style
>
> data MyArrow a b = MyArrow (a -> (String, b))
>
> will not work.
>
> Now I have a problem with the definition of "pure" and
> "first". At first, I declared
>
> pure f = MyArrow (\(s, x) -> (s, f x))
> first (MyArrow f) = MyArrow (\(s, (x, y)) -> let (s',
> z) = f (s, x) in (s', (z, y)))
>
> this seems to work, but then I begin to have problems
> with the "data-plumbing" pure arrows, e.g. in
>
> pure (\x -> (x, x)) >>> first someArrow >>>> pure
> (\(_, x) -> x)
>
> Ideally, this arrow will preserve whatever information
> I put there for the input, but because "first
> someArrow" will change the WHOLE information
> associated with the pair of result, I can't find any
> way to let "pure (\(_, x)->x)" (which is an extremely
> generic function) retrieve the PART of information for
> the second piece in the pair tuple.
>
> I thought about this a lot, but it seems to me that
> the only way to solve this is to somehow make the
> information "lookupable" from the data itself, not
> "placed beside" the data, but how I can do that? And
> can there be some other solution to this?
>
> Thanks very much!
>
> Di, Yu

What are you trying to do here? From the type of the arrow you are trying
to define it looks like pure functions on (String,a) pairs should work
just as well. Whatever you are doing, I would guess that the tagging is
fairly orthogonal to the use of arrows. I think you can probably get by
with pure functions on pairs of strings and values, with a few lifting
combinators.

For example, if I assume that the tags are used so functions can add
comments on the values as they pass through you might write something like

type Annotated a = (String,a)
comment :: String -> Annotated a -> Annotated a
comment newcomment (comments,val) = (newcomment++comments,val)

liftAnn2 f (c1,a) (c2,b) = (c1++c2,b)
plusAnn x y = comment "Added two numbers"

Now you can define functions like
addThree x y z = plusAnn x (plusAnn y z)
and run compuatations like
addThree ("One",1) ("Two",2) ("Three",3)
and get results like
("Added two numbersOneAdded two numberTwoThree",6)

Obviously the policy for combining tags is pretty bad, but you could fill
in whatever you wanted.

I must say I'm pretty dubious though. It sounds like you intend to compute
over these tagged values and combine them. The only sensible use of string
tags on values passed freely around that I can think of is building up a
representation of the computation that produced the value, like the R.hs
module by Claus Reinke. To do that one tag per arrow is exactly what you
want. For most other uses I think the tag should probably be a data
structure rather than a string. If the values are sitting in a data
structure (like an association like) it's a different story, of course.
I could help more if I had a better idea what your purpose is.

Brandon



More information about the Haskell mailing list