Haskell 使用foldr的教堂

Haskell 使用foldr的教堂,haskell,Haskell,我遇到了这个代码,它的工作,但我不知道为什么。我将尝试传达我理解的部分,但我不了解全部情况。代码如下: church :: Int -> (c -> c) -> c -> c church 0 _ arg = arg church n f arg = foldr (\x acc -> f acc) arg [1..n] 在前奏曲上运行此输入时 church 4 tail "ABCDEFGH" 答案是: "EFGH" 我知道foldr的工作原理,我可以浏览fo

我遇到了这个代码,它的工作,但我不知道为什么。我将尝试传达我理解的部分,但我不了解全部情况。代码如下:

church :: Int -> (c -> c) -> c -> c
church 0 _ arg = arg
church n f arg = foldr (\x acc -> f acc) arg [1..n]
在前奏曲上运行此输入时

church 4 tail "ABCDEFGH" 
答案是:

"EFGH"
我知道foldr的工作原理,我可以浏览foldr的一个示例:

foldr (/) 2 [8,12,24,4]
这里发生的是:

4/2 = 2, 24/2 = 12, 12/12 = 1, 8/1 = 8
我得到所需的输出8,如第二个示例所述:

至于这个问题,我知道为什么“EFGH”是答案。尾部应用四次,如下所示:

tail "ABCDEFGH" = "BCDEFGH", 
tail "BCDEFGH" = "CDEFGH"
tail "CDEFGH" = "DEFGH"
tail "DEFGH" = "EFGH"
但是,在这段代码中,这是我写出来的过程:

foldr (\x acc -> tail acc) "ABCDEFGH" [1, 2, 3, 4]

根据我在上文中对
foldr
的描述,
foldr
将tail和
“ABCDEFGH”
应用于4,因为4是最后一个元素。但是,我无法理解
“ABCDEFGH”
是如何以4结尾应用的。在我的示例中,这很容易,因为
(/)
将两个元素分开,一个来自列表,另一个是第二个参数。然而,在本代码中,tail用于列表中的一个元素和另一个列表中的一个元素之间。我不明白。有人能帮我一个接一个地浏览元素吗,就像我在示例中所描述的那样?

请注意,
x
->
右边的任何地方都没有使用。因此,列表中的数字没有被使用。它可以是一个单位列表,但仍然可以工作:
foldr(\x acc->tail acc)“ABCDEFGH”[(),(),(),(),()]
该列表的唯一目的是在其长度中编码要执行
tail
的次数。如果将
\x acc->tail acc
替换为等效表达式
const tail

,也可能有助于您理解。函数生成一个1到N的列表,就foldr而言,它在列表上执行了4次操作,但在这种情况下,
x
实际上被忽略,操作仅在
arg
在您的情况下,它是主要输入。我明白了,这是一个很好的解释,谢谢!