Wiring/ArrowLooping every element in a list with every other element in the list

106 views Asked by At

I asked a question about this earlier but I don't think I really knew what I was asking. I think I understand my problem slightly better now.

I'm using netwire, an arrowized FRP library, and having some trouble getting this arrowloop implemented.

I have

f :: ArrowLoop r =>  a  -> r [a]  a
g :: ArrowLoop r => [a] -> r ()  [a]

Such that g basically ties every element in the given list with the list of every other element using f...um...this is hard to really say using words so I'll give an example with a list of length 4:

g [x0, x1, x2, x3] = proc _ -> do
  rec
     y0 <- f x0 -< [y1, y2, y3]
     y1 <- f x1 -< [y0, y2, y3]
     y2 <- f x2 -< [y0, y1, y3]
     y3 <- f x3 -< [y0, y1, y2]
  returnA -< [y0, y1, y2, y3]

(I have a helper function selects :: [a] -> [(a,[a])], that turns something like [x,y,z] into [(x, [y,z]), (y, [x,z]), (x, [x,y])])

Now...I've compiled this hard-coded version and this already works and delivers exactly the results that I wanted mostly. It runs without any funky <> issues.

Does anyone know if it's possible to do this "exact" thing...but with a general number of list elements?


For reference, my implementation of selects comes from Simon Marlow,

selects :: [a] -> [(a,[a])]
selects = go []
  where
    go xs [] = []
    go xs (y:ys) = (y,xs++ys) : go (y:xs) ys
1

There are 1 answers

2
shang On

I couldn't test this properly since I didn't have any example f to run it against but I believe this generalizes the arrow pattern you have:

g :: ArrowLoop r => [a] -> r () [a]
g = listLoop . map f

listLoop :: ArrowLoop r => [r [a] a] -> r () [a]
listLoop l = const [] ^>> go l where
    go []     = arr (const [])
    go (r:rs) = proc bs -> do
        rec a  <- r     -< bs ++ as
            as <- go rs -< bs ++ [a]
        returnA -< a : as

So first we map with f to get the list of arrows [f x0, f x1, ...] and then we feed it to a combinator I named listLoop which takes a list of arrows and defines a recursive arrow which essentially has the same logic as your selects. bs is the list of results from arrows preceding r (analogous to xs in selects) and as are the results from the arrows following r. For each r we feed in the results of the other arrows but not the result of r itself (which is a). Then we recurse, appending a to the list of preceding results.