确切地知道这是做什么的,或者在函数中输入什么以在输出中找到模式
f0 f id [] = id
f0 f id (x:xs) = f x (f0 f id xs)
答案 0 :(得分:4)
f
和id
保持不变,所以让我们稍微简化一下:
f0 [] = id
f0 (x:xs) = f x (f0 xs)
这意味着f0 xs
可以扩展为:
f x1 (f x2 (f x3 id))
哪种类似于foldr
。那是因为它是foldr
。
Prelude> foldr (+) 0 [1, 2, 3]
6
Prelude> f0 (+) 0 [1, 2, 3]
6
答案 1 :(得分:4)
好的。让我们来看看吧。这是一个带有基本案例和递归步骤的递归函数。它的名称为f0
,有三个参数,f
,id
(令人困惑的是与Prelude中的函数同名)和(x:xs)
。不幸的是,它没有类型签名,但我们已经可以告诉第三个是某种列表。所以它的签名就像f0 :: a -> b -> [c] -> d
基本情况很简单:如果第三个参数是空列表,则函数返回id
,因此具有函数返回的类型。所以这两种类型是相同的,我们可以将类型签名细化为f0 :: a -> b -> [c] -> b
。
仅当列表(x:xs)
不为空时才会调用递归案例。它调用f
,因此必须是两个参数的函数,x
(列表的头部)作为f
的第一个参数,并调用f0
}作为第二个参数。由于f
的返回值是f0
的有效返回值,因此它们必须具有相同的返回类型。因此,我们可以推断,如果b
是f0
的返回类型和[a]
第三个参数的类型,则此函数的签名必须是:
f0 :: (a -> b -> b) -> b -> [a] -> b
现在,让我们仔细看看递归步骤中f
的第二个参数。它调用f0 f id xs
,这是完全相同的调用,但是调用列表的尾部。 (因此,列表会在每个步骤中缩短一个元素,直到它为空并且我们达到基本情况,因此算法必须终止。)因此,f0 (+) 0.0 [1,2,3]
会扩展为1 + (2 + (3 + 0.0) )
。这是Prelude的功能;你能分辨出来吗?
编辑:另一个答案破坏了它,但我会注意到这些名字也是提示。 f0
和f
是函数,id
是标识元素的缩写(因为预期的模型是您将其添加到列表的最后一个元素并返回相同的元素,添加3 + 0.0的方式可以获得浮点数3.0),而 x:xs 是传统的方式来引用列表参数递归函数。
答案 2 :(得分:0)
要解密代码,我有时会发现利用Data.SimpleReflect
并运行一些测试很有用。
> import Debug.SimpleReflect
> let f0 f id [] = id ; f0 f id (x:xs) = f x (f0 f id xs)
> f0 f a [b,c,d,e]
f b (f c (f d (f e a)))
看起来很熟悉......是foldr
吗?
> foldr f a [b,c,d,e]
f b (f c (f d (f e a)))
好的,是的。