使用箭头折叠元组列表

问题描述 投票:0回答:1

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

考虑以下实施:

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')
类型的库函数,或者可能是一种完全不同的方法。

haskell tuples arrow-abstraction
1个回答
9
投票

Control.Arrow
不太关注高阶函数。你真正想要的是一个函数
foo :: (a -> a' -> a'') -> (b -> b' -> b'') -> (a,b) -> (a',b') -> (a'',b'')
,类似于 arity 2 函数的
(***)
。 Data.Biapplicative 中有这样一个函数(来自 bifunctor 包),它具有更通用的签名
biliftA2 :: Biapplicative w => (a -> b -> c) -> (d -> e -> f) -> w a d -> w b e -> w c f
。由于二元素元组有一个 Biapplicative 实例,这就是您所需要的。

我对你的代码的唯一抱怨是,它的 lambda 的柯里化是不明显的;我可能更喜欢更明确的

\(a,b) (a',b') -> (lfn a a', rfn b b')

编辑备注:我的结论是所需的功能不存在,并建议定义它;在 Carl 的评论的刺激下,我在 Biapplicative 中找到了这个(更通用的类型签名阻止了 Hoogle 在我建议的签名下找到它)。

© www.soinside.com 2019 - 2024. All rights reserved.