我早些时候问了一个问题,但我不认为我真的知道我在问什么。我想我现在对我的问题了解得更好了。
我正在使用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
答案 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
具有相同的逻辑。 bs
是r
之前的箭头(类似于xs
中的selects
)的结果列表,as
是r
之后的箭头的结果}。对于每个r
,我们会输入其他箭头的结果,但不会输入r
本身的结果(a
)。然后我们递归,将a
附加到前面的结果列表中。