List 福尔德混乱

List 福尔德混乱,list,haskell,lambda,List,Haskell,Lambda,我在解释器上执行此语句 foldr (\x (a, b) -> if x == '_' then (a+1, [((div a 3), (mod a 3))] ++ b) else (a, b)) (0, []) "_______OX" 我希望输出是 (7,[(0,0),(0,1),(0,2),(1,0),(1,1),(1,2),(2.0)]) 然而,输出是 (7,[(2,0),(1,2),(1,1),(1,0),(0,2),(0,1),(0,0)]) 我做错了什么。据我所知,fol

我在解释器上执行此语句

foldr (\x (a, b) -> if x == '_' then (a+1, [((div a 3), (mod a 3))] ++ b) else (a, b)) (0, []) "_______OX"
我希望输出是

(7,[(0,0),(0,1),(0,2),(1,0),(1,1),(1,2),(2.0)])
然而,输出是

(7,[(2,0),(1,2),(1,1),(1,0),(0,2),(0,1),(0,0)])
我做错了什么。据我所知,foldr从列表的最后一个元素开始,我的lambda函数将它附加到累加器列表的开头。所以我应该得到(0,0)作为第一个元素。然而,情况恰恰相反,我感到困惑(

还有一个小问题-我如何为类似的问题分配标签?

在“X”之后

    (0,[])
    (0,[])
    (1,[(0,0)])
    (2,[(0,1),(0,0)]) -- you prepend in: [((div a 3), (mod a 3))] ++ b
    (3,[(O,2),(0,1),(0,0)])
在“0”之后,您有

    (0,[])
    (0,[])
    (1,[(0,0)])
    (2,[(0,1),(0,0)]) -- you prepend in: [((div a 3), (mod a 3))] ++ b
    (3,[(O,2),(0,1),(0,0)])
在第一次之后

    (0,[])
    (0,[])
    (1,[(0,0)])
    (2,[(0,1),(0,0)]) -- you prepend in: [((div a 3), (mod a 3))] ++ b
    (3,[(O,2),(0,1),(0,0)])
第二次之后,你有

    (0,[])
    (0,[])
    (1,[(0,0)])
    (2,[(0,1),(0,0)]) -- you prepend in: [((div a 3), (mod a 3))] ++ b
    (3,[(O,2),(0,1),(0,0)])
第三次之后你有

    (0,[])
    (0,[])
    (1,[(0,0)])
    (2,[(0,1),(0,0)]) -- you prepend in: [((div a 3), (mod a 3))] ++ b
    (3,[(O,2),(0,1),(0,0)])

为了更好地解释,让我们简化一下:

foldr (\c (a,b) -> (a+1, a:b)) (0, []) "hi"
Foldr定义为

foldr f a [] = a
foldr f a (x:xs) = f x (foldr f a xs)
让我们调用lambda函数
g
因此,上述表达式的轨迹:

g 'h' (foldr g (0,[]) "i") 
g 'h' (g 'i' (foldr g (0,[]) ""))
g 'h' (g 'i' (0, []))
g 'h' (1, [0])
(2, [1,0])

如果
(0,0)
是添加到列表中的第一个元素,那么它将是列表中的最后一个元素。这是您感到困惑的原因吗?为了更好的可读性,您可以始终将
[a]++b
替换为
a:b
(a):b
(取决于a的形式,但在大多数情况下它只是
a
)。此外,
((a),(b))
始终可以写入
(a,b)
@pubby,是的。首先读取的元素不是成为最终列表中的最后一个元素吗?顺便说一句,由于懒惰,您传递给
foldr
的函数实际上需要消耗多少列表才能产生结果。这意味着
foldr
仍然从左到右工作-它开始计算f可能递归之前的列表头。