【问题标题】:Employing arrows to fold a list of tuples使用箭头折叠元组列表
【发布时间】:2013-05-21 18:14:43
【问题描述】:

有时您想使用不同的折叠函数将一组元组折叠成一个元组。例如,为了将 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 arrows


【解决方案1】:

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 在我建议的签名下找到它)。

【讨论】:

  • 使用\(a,b) (a',b') -> ... 进行手动元组分解有点违背使用一些奇特概念来编写全能单行代码的全部目的。感谢您提及 Biapplicative,我会调查一下。
  • 我的意思是,即使 Biapplicative 的 (<<**>>) 确实具有您需要应用 (lfn *** rfn) 的类型,但在这里对箭头的调用似乎不合适。但这只是我的直觉;基于箭头的方法是正确的,即使不一定清楚。但我确实更喜欢 (lfn `biLiftA2` rfn) 到显式 lambda。
猜你喜欢
  • 1970-01-01
  • 2017-07-10
  • 2019-07-01
  • 2012-08-13
  • 2019-01-09
  • 2018-12-24
  • 2020-06-11
  • 2020-09-01
  • 2010-11-25
相关资源
最近更新 更多