为什么这个表达式相等?

时间:2016-08-27 13:21:02

标签: haskell

我现在正在学习Haskell并且我读了一本名为“使用Haskell进行功能性思考”的书,我无法理解为什么第一章的表达式为真:

  总结。 map sum = sum。的concat

2 个答案:

答案 0 :(得分:5)

非正式地说,这只是说因为如果添加是关联的,那么对你添加的数字进行分组并不重要。 (a + b) + (c + d)(a + b + c + d)相同。

在形式上,我们可以使用等式推理和结构归纳来证明任何大小的列表。 (有关这两个过程的快速定义,请参阅最后的内容。)

假设mapconcatsum(.)的以下定义:

  1. map sum [] = []
  2. map sum (a:as) = sum a : map sum as
  3. concat [] = []
  4. concat (a:as) = a ++ concat as
  5. sum [] = 0
  6. sum (a:as) = a + sum as
  7. (f . g) x = f (g x)
  8. 为了使证明更简单,我们会在没有明确证据的情况下声明(但请参阅下文)

    1. sum (a ++ b) == sum a + sum b
    2. 首先,我们确定空列表的标识是真的。

      (sum . map sum) [] == sum (map sum [])  -- (7)
                         == sum []            -- (1)
                         == sum (concat [])   -- (3)
                         == (sum . concat) [] -- (7)
      

      (请注意,我们不需要定义5,因为空列表是空列表。)

      现在,为大小为as的任何列表k添加新定义。

      1. (sum . map sum) as == (sum . concat) as
      2. 如果(9)为真,我们可以证明大小为k+1的列表的身份:

        (sum . map sum) (a:as) == sum (map sum (a:as))        -- (7)
                               == sum (sum a : map sum as)    -- (2)
                               == sum a + sum (map sum as)    -- (6)
                               == sum a + (sum . map sum) as  -- (7)
                               == sum a + (sum . concat) as   -- (9)
                               == sum a + sum (concat as)     -- (7)
                               == sum (a ++ concat as)        -- (8)
                               == sum (concat (a:as))         -- (4)
                               == (sum . concat) (a:as)       -- (7)
        

        通过归纳,我们已经为任何大小的列表证明了sum . map sum == sum . concat

        • 等式推理意味着我们可以使用a = b这样的平等来将a替换为bb替换为a我们的证明。

        • 列表上的结构感应是一个自举过程。您假设某些属性适用于大小为k的列表,然后使用它来证明大小为k+1的列表是正确的。然后,如果你能证明k=0是真的,那么这意味着所有k都是如此。例如,如果k=0为真,则k=1为真,这意味着k=2等等。

        定义4假设++

        的定义
        [] ++ bs = bs
        (a:as) ++ bs = a : (as ++ bs)
        

        定义++后,我们可以证明(8):

        基本案例:a为空

        sum ([] ++ b) == sum b               -- definition of ++
                      == 0 + sum b           -- definition of +
                      == sum [] + sum b      -- definition of sum
        

        假设sum (a++b)的{​​{1}}长度为a

        k

答案 1 :(得分:1)

想象一下,我们有一个清单:

myList :: [[Int]]
myList = [[1,2],[3,4,5]]

让我们申请sum . map sum

  (sum . map sum) [[1,2],[3,4,5]]
= sum [sum [1,2], sum [3,4,5]]
= sum [1+2,3+4+5]
= 1+2+3+4+5

现在让我们应用sum . concat

   (sum . concat) [[1,2],[3,4,5]]
 = sum [1,2,3,4,5]
 = 1+2+3+4+5

希望你现在可以看到,因为(a + b)+ c = a +(b + c),我们添加东西的顺序无关紧要,因此对内部列表求和,然后对整个列表求和产生与简单地对内部列表的每个值求和相同的结果。