Haskell 使用箭头折叠元组列表

Haskell 使用箭头折叠元组列表,haskell,tuples,arrows,Haskell,Tuples,Arrows,有时,您需要使用不同的折叠函数将元组列表折叠为一个元组。例如,为了将运行状态结果列表粘合在一起,需要(在某种意义上)获得一个组合状态和一个组合结果 考虑以下实施: wish :: (a -> a' -> a) -> (b -> b' -> b) -> (a,b) -> [(a', b')] -> (a,b) wish lfn rfn x xs = foldl (\(a,b) -> (lfn a) *** (rfn b)) x xs 虽然它有

有时,您需要使用不同的折叠函数将元组列表折叠为一个元组。例如,为了将运行状态结果列表粘合在一起,需要(在某种意义上)获得一个组合状态和一个组合结果

考虑以下实施:

wish :: (a -> a' -> a) -> (b -> b' -> b) -> (a,b) -> [(a', b')] -> (a,b)
wish lfn rfn x xs = foldl (\(a,b) -> (lfn a) *** (rfn b)) x xs

虽然它有效,但我对这个lambda感到不舒服
lfn***rfn
本身就有一种类型的
(a,b)->(a->a',b->b')
,如果不借助模式匹配,我无法找到正确应用于元组的方法。有没有一种清晰优雅的方式让我错过了?它可能是
(a,a')->(a->a,a'->a')->(a,a')
类型的库函数,也可能是一种完全不同的方法。

控件。Arrow
不太注意更高的算术函数。你真正想要的是一个函数
foo::(a->a'->a'->a'->b'->b'->b'->(a,b)->(a',b'->(a'',b')->(a'',b'')
,类似于算术2函数的
(***)
。在Data.Biapplicative(来自包bifunctor)中有这样一个函数,它具有更一般的签名
bilita2::Biapplicative w=>(a->b->c)->(d->e->f)->wad->wb e->wc f
。因为有两个元素元组的双应用实例,所以这就是您所需要的

我能看到的对你的代码的唯一抱怨是,它对lambda的教唆是不明显的;我可能更喜欢更明确的
\(a,b)(a',b')->(lfna',rfnbb')


编辑注释:我认为所需的功能不存在,并建议定义它;在Carl的评论的刺激下,我发现了一个双应用类(更通用的类型签名阻止Hoogle在我建议的签名下找到它)。

某种双应用类就可以了。。可能在hackage的某个地方有一个,但我将把它留给其他人来讨论哪些是好的,哪些不是不推荐的。它在Hackage上的实例化,使用
\(a,b)(a',b')->…
进行手动元组分解,这有点违背了使用一些奇特的概念来编写强大的一行程序的全部目的。感谢您提到BiApplication,我将对此进行研究。我的观点是,尽管BiApplication的
()
确实有您需要应用的类型
(lfn***rfn)
,但在这里调用箭头似乎不合适。但这只是我的直觉;基于箭头的方法是正确的,如果不一定清楚的话。但是我更喜欢
(lfn`biLiftA2`rfn)
而不是显式lambda。