【问题标题】:outer product -> partially applied functions -> composition外积 -> 部分应用函数 -> 组合
【发布时间】:2016-05-11 14:20:00
【问题描述】:

我有一个二进制函数列表,例如(a -> b -> a) 和一个项目列表[b]。我需要产生一个转换(a -> a),如下所示。对于每个 bs,我需要部分应用函数并生成它们的组合,这给了我一个与 bs 长度相同的一元函数列表。将这些组合中的每一个称为处理器;接下来我需要组成处理器。例如,如果我有函数[f0,f1] 和项目[b0,b1],我需要函数(f1 b1) . (f0 b1) . (f1 b0) . (f0 b0)。我可以看到我正在折叠 bs,但这看起来也像是一个外部产品的组合。那么,Haskell 是否提供了一种巧妙的方法来使用某种外部产品来生产它? (当然,顺序很重要。)如果是这样,请用完全新手可以理解的术语进行解释。

【问题讨论】:

  • 我说看看<*> in Control.Applicative
  • 你想如何确定构图的顺序?您举了一个长度为 2 的列表的示例,但是 3、4...应该是什么?

标签: haskell


【解决方案1】:

有关仅使用标准函数的解决方案,请参阅 ThreeFx's answer


您还需要使用(.) 折叠部分应用函数列表本身。

首先,获取部分应用函数的列表:

-- If f :: a -> b -> a, then (`f` b) :: a -> a
[ (`f` b) | b <- [b0, b1], f <- [f0, f1] ]
-- Result: [(`f0` b0), (`f1` b0), (`f0` b1), (`f1` b1)]

(使用fs &lt;*&gt; bs 会很好,但您需要将f 部分应用到它的第二个 参数,而不是第一个参数,并且结果列表的组合步骤顺序错误.)

接下来,使用(.) 折叠该列表。我永远记不清要使用哪个折叠(或如何使用它来确保您需要的正确排序),所以这是一个我知道做正确事情的自定义递归函数:

composeAll :: [(a -> a)]
composeAll [] = id
composeAll (f:fs) = composeAll fs . f

把它们放在一起:

fs = [f0, f1, f2]
bs = [b0, b1, b2]
f = composeAll [(`f` b) | b <- bs, f <- fs]

【讨论】:

  • 错误的顺序是通过使用&lt;**&gt; 来修复的,基本上是&lt;*&gt;,它的参数颠倒了。
  • 另外,composeAllfoldr (flip (.)) id 相同。
  • 谢谢;我将按原样保留我的答案,作为对仅标准功能的答案的“简化”补充。
【解决方案2】:

您可以使用&lt;**&gt;(位于Control.Applicative)和fold 结果:

combine :: [(a -> b -> a)] -> [b] -> (a -> a)
combine fs bs = foldr (flip (.)) id $ bs <**> (map flip fs)

让我们看看组件:

map flip fs

这只是将函数从a -&gt; b -&gt; a 翻转到b -&gt; a -&gt; a,以便我们稍后可以ap 它们。

bs <**> (map flip fs)
-- ex: [b0, b1] <**> [f0, f1] == [f0 b0, f1 b0, f0 b1, f1 b1]

此函数将所有bs 部分应用于fs 并将它们放入列表中。我们现在要做的就是使用组合运算符 ((.)) 将结果 fold。请注意,使用flip (.) 我们颠倒了组合顺序,因为&lt;**&gt; 生成的列表与我们想要的相反:

foldr (flip (.)) id $ it -- alternatively foldr1
-- ex: foldr (flip (.)) id [f0 b0, f1 b0, f0 b1, f1 b1] ==
--     (f1 b1) . (f0 b1) . (f1 b0) . (f0 b0)

【讨论】:

  • 不错;我不知道&lt;**&gt;
  • 我发现 zipWith flip fs bsbs &lt;**&gt; (map flip fs) 更具可读性。
猜你喜欢
  • 1970-01-01
  • 2015-07-31
  • 2011-12-02
  • 2013-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多