【问题标题】:Understanding function composition with negate用否定理解函数组合
【发布时间】:2013-06-24 01:04:52
【问题描述】:

阅读an awesome site 的高阶函数页面后,我仍然无法理解与函数组合配对的否定函数。

更具体地说,看这段代码:

ghci> map (negate . sum . tail) [[1..5],[3..6],[1..7]]

产生:

[-14,-15,-27] 

我再次重新阅读了该页面,但老实说,我仍然不知道那行代码是如何产生这个答案的,如果有人能指导我完成这个过程,我将非常感激!

【问题讨论】:

  • 你可以从这样一个管道的左边删除任意数量的函数,看看发生了什么。

标签: haskell function-composition negate


【解决方案1】:
map f [a,b,c] = [f a,  f b,  f c]

因为map f (x:xs) = f x:map f xs - 将f 应用于列表的每个元素。

所以

map (negate.sum.tail) [[1..5],[3..6],[1..7]]
= [(negate.sum.tail) [1..5],   (negate.sum.tail) [3..6],   (negate.sum.tail) [1..7]]

现在

(negate . sum . tail) [1..5]
= negate (sum (tail [1,2,3,4,5]))
= negate (sum  [2,3,4,5])
= negate 14
= -14

因为(f.g) x = f (g x). 是右关联的,所以(negate.sum.tail) xs = (negate.(sum.tail)) xs 又是negate ((sum.tail) xs) = negate (sum (tail xs))

tail 为您提供除了列表的第一个元素之外的所有内容:tail (x:xs) = xs,例如 tail "Hello" = "ello" sum 按您的预期将它们相加,而
negate x = -x

其他的工作类似,减去每个列表尾部的总和。

【讨论】:

  • 我不确定调用tail 是幸运的。在其他设置(Java,...)中,“tail”通常用于表示链表的最后一个节点,使用更清晰的措辞可能会更好。不幸的是,“除了第一个元素之外的所有元素”都太笨拙了。
  • @DanielFischer 干杯。编辑使tail 功能更加明确。
  • 太棒了。不过,我不会费心去取消和重新投票来表达我的感激之情。
  • @Daniel Fischer 这也让我感到困惑,因为在 C++ 中,我总是将链表的结束节点命名为 tail
【解决方案2】:

为了给 AndrewC 的出色答案添加不同的视角,我通常会根据 functor lawsfmap 来考虑这些类型的问题。由于map 可以被认为是fmap 对列表的特化,我们可以将map 替换为更通用的fmap 并保持相同的功能:

ghci> fmap (negate . sum . tail) [[1..5],[3..6],[1..7]]

现在我们可以使用代数替换来应用合成函子定律来移动合成发生的位置,然后将每个函数单独映射到列表中:

fmap (f . g)  ==  fmap f . fmap g -- Composition functor law

fmap (negate . sum . tail)             $ [[1..5],[3..6],[1..7]]
== fmap negate . fmap (sum . tail)     $ [[1..5],[3..6],[1..7]]
== fmap negate . fmap sum . fmap tail  $ [[1..5],[3..6],[1..7]]
== fmap negate . fmap sum $    fmap tail [[1..5],[3..6],[1..7]]
== fmap negate . fmap sum              $ [tail [1..5],tail [3..6],tail [1..7]] -- As per AndrewC's explanation
== fmap negate . fmap sum              $ [[2..5],[4..6],[2..7]]
== fmap negate                         $ [14, 15, 27]
==                                       [-14, -15, -27]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-27
    • 1970-01-01
    • 2018-04-18
    • 2021-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多