On Tue, May 10, 2011 at 1:25 PM, Adam Megacz
<megacz@cs.berkeley.edu> wrote:
> class (GArrowMap a (**) u c) => GArrowJoin a (**) u c where
> join :: a d (c r) -> a (c d) (c r)
I like these; I think you're on the right track. The last one reminds
me of concatMap.
That might be a better name for it. I was thinking in terms of a relational join.
Perhaps what you want is
gac_drop :: a (c u) u
... which is a bit like ga_cancell and ga_cancelr, but for a whole
collection rather than one input at a time.
That sounds reasonable, but also looks like users would need mapA to ever leverage it. I was imagining that some models might provide mapA_ without mapA, i.e. only allowing further composition through side-effects similar to a 'for' loop in a C-family language. This is not very composition friendly, of course, but it might be easier to implement and sufficient for the job.
-- | process each element in a collection, then cancel it.
class (GArrow a (**) u) => GArrowMap_ a (**) u c where
ga_map_ :: a d u -> a (c d) u
-- | process each element in a collection; the result is subject to
-- further composition.
class (GArrowMap_ a (**) u c) => GArrowMap a (**) u c where
ga_map :: a d r -> a (c d) (c r)
By the way, I've started [2] using type families for the "aggregate"
GArrow classes like GArrowSTLC. This greatly reduces the syntactic
noise in the types -- you only have one type parameter instead of four.
The price is that a single type can't be an instance of these classes in
more than one way (see Section 3.6.1 of [3] for why this is important).
Sounds good. I look forward to seeing where that goes. I use type and data families quite heavily in my own models - they're much friendlier for inference.
> In my own case, 'c' might be representing an asynchronous or
> distributed, reactive collection, so the ability to restrict
> expressiveness is important for performance.
Certainly. The multiplicative disjunction [4] of linear logic is the
"binary" version of this: (A \bindnasrepma B) is sort of like an A and a
B in geographically distant locations; if you have a (Int \bindnasrepma
Int) you have two Int's, but in order to (for example) add them together
you must use some sort of communication primitive to get them both to
the same place.
I must admit to some confusion that you likened asynchronous/distributed products used in 'synch' to 'additive conjunction' in the earlier message (help for asynchronous arrows) and the same concept to multiplicative disjunction here.
Elements in such a product may exist at different times (i.e. production latencies from some initial event) as well as different locations.
It sounds like you want a sort of "collection version" of multiplicative
disjunction. I bet Data Paralell Haskell's parallel array type-former
(([::]) :: * -> *) would be an instance of this class.
Data Parallel Haskell is all about performance, doesn't really admit to parallel semantics or asynchronous side-effects as a result of mapping arrows across the collection. To the extent it qualifies, I suspect so would a normal list.
Dave