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]))部分与(+)不兼容。然而,这个功能是有效的,所以我在阅读或转换错误的内容是什么?
答案 0 :(得分:3)
您找到的功能问题是:
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
。它们完全不同。如果它看起来像你可能会更好理解:
f'
它做了什么,将累加器更改为列表,因为scanl会累积,但它会保留所有路径通过原始列表。因此,cons (:)
f
是一个新的头,将函数head
应用于列表的实际元素和累加器的{{1}}。