使用箭头折叠元组列表

时间:2013-05-21 18:14:43

标签: haskell tuples arrows

有时您希望使用不同的折叠函数将元组列表折叠为一个元组。例如,为了将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')类型的库函数,也可能是完全不同的方法。

1 个答案:

答案 0 :(得分: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的curry是不明显的;我可能更喜欢更明确的\(a,b) (a',b') -> (lfn a a', rfn b b')

编辑笔记:我得出结论,所需的功能不存在,并建议定义它;在Carl的评论的推动下,我发现了Biapplicative中的那个(更普遍的类型签名阻止了Hoogle在我建议的签名下找到它)。