扫描器的定义如何在foldr工作?

时间:2015-02-21 20:54:17

标签: haskell fold

Haskell Wikibook第102页的练习1要求"编写自己的scanr定义,首先使用递归,然后使用foldr。"我写了一个递归的:

myscan f acc []     = [acc]
myscan f acc (x:xs) = val : rest where
    val  = f x (head rest)
    rest = myscan f acc xs

...但无法找出折叠版本。我最终用Google搜索并找到了答案:

myscan2 f acc xs = foldr f' [acc] xs where
    f' x xs = (f x (head xs)) : xs

显然它有效,但对我来说没有意义。使用参数

(+) 0 [1,2,3]

......它变成了这样的东西:

myscan2 (+) 0 [1,2,3] = foldr f' [0] [1,2,3] where
    f' [0] [1,2,3] = ((+) [0] (head [1,2,3])) : [1,2,3]

...但是((+)[0](头[1,2,3]))部分与(+)不兼容。然而,这个功能是有效的,所以我在阅读或转换错误的内容是什么?

1 个答案:

答案 0 :(得分:3)

您找到的功能问题是:

  1. xs myscan2 f acc xs = foldr f' [acc] xs上的f' x xs = (f x (head xs)) : xs不一样 myscanr f acc xs = foldr f' [acc] xs where f' b a = (f b (head a)) : a
  2. 它们完全不同。如果它看起来像你可能会更好理解:

    f'

    它做了什么,将累加器更改为列表,因为scanl会累积,但它会保留所有路径通过原始列表。因此,cons (:) f是一个新的头,将函数head应用于列表的实际元素和累加器的{{1}}。