Haskell 就foldr而言,scanr的定义是如何工作的?
Haskell Wikibook第102页的练习1要求“编写您自己的scanr定义,首先使用递归,然后使用foldr。”我编写了一个递归定义:Haskell 就foldr而言,scanr的定义是如何工作的?,haskell,fold,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 …但无法找到foldr版本。我最终在谷歌上找到了这个答案: myscan2 f acc xs = foldr f
myscan f acc [] = [acc]
myscan f acc (x:xs) = val : rest where
val = f x (head rest)
rest = myscan f acc xs
…但无法找到foldr版本。我最终在谷歌上找到了这个答案:
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])部分与(+)的类型不兼容。但是,该函数可以正常工作,因此,我读取或转换的内容不正确吗?您发现的函数问题是:
xs
与f'xxs=(fx(头xs)):xs
myscanr f acc xs = foldr f' [acc] xs
where f' b a = (f b (head a)) : a
它所做的是,将累加器更改为一个列表,因为scanl accumlate但它保留了通过原始列表的所有路径。因此,
f'
cons(:)
将函数f
应用于列表的实际元素和累加器的head
。这是一个简单的转换错误,可能是由于它们的哑参数名。它应该是(+)3(头[0]):[0]
。累加器是foldr
函数的第二个输入,但出于某种疯狂的原因,它们调用累加器参数xs
。显然,您必须应用reverse
,因为返回的列表是向后的。我不认为它是向后的。毕竟,这是一次正确的扫描。另外,您将x
重命名为b
,我认为将其保留为x
会更有意义。您是对的。我弄错了:/itsscanr
,但我重新命名了两者,以表明,f'
与myscanl f acc xs=foldr f'[acc]xs
上的变量没有直接关系(当然,它们可以根据您的意愿命名),它的好名字是b
asx
,创造了更多的语义。如果它是scaner
,我就不会叫它myscanl
!谢谢你。我可以在纸上追踪工作,即使我还不能在心里摸索。期待当它不再是高深莫测的异族象征意义的时候。:)