Wiring / ArrowLooping列表中的每个元素与列表中的每个其他元素

时间:2014-01-18 12:02:40

标签: haskell arrows netwire

我早些时候问了一个问题,但我不认为我真的知道我在问什么。我想我现在对我的问题了解得更好了。

我正在使用netwire,一个箭头化的FRP库,并且在实现这个arrowloop时遇到了一些麻烦。

我有

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

这样g基本上将给定列表中的每个元素与使用f的所有其他元素的列表联系起来......嗯...这很难用词来说明,所以我会举一个长度为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]

(我有一个帮助函数selects :: [a] -> [(a,[a])],将[x,y,z]转换为[(x, [y,z]), (y, [x,z]), (x, [x,y])]

现在......我已经编译了这个硬编码版本,这已经有效,并且提供了我想要的结果。它没有任何时髦的运行&lt;&gt;的问题。

有没有人知道是否可以做这个“确切”的事情......但是有一般数量的列表元素?


作为参考,我对selects的实施来自Simon Marlow,

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

1 个答案:

答案 0 :(得分:2)

我无法正确测试,因为我没有任何示例f可以对其进行测试,但我相信这会概括您的箭头模式:

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

首先,我们使用f进行映射以获取箭头[f x0, f x1, ...]的列表,然后我们将其提供给名为listLoop的组合器,该组合器获取箭头列表并定义递归箭头它基本上与您的selects具有相同的逻辑。 bsr之前的箭头(类似于xs中的selects)的结果列表,asr之后的箭头的结果}。对于每个r,我们会输入其他箭头的结果,但不会输入r本身的结果(a)。然后我们递归,将a附加到前面的结果列表中。