折叠和折叠的长度

joe*_*err 2 haskell fold

我有两个函数来计算整数列表的长度

lengthFoldl :: [Int] -> Int
lengthFoldl xs = (foldl (\_ y -> y+1) 0 xs)
Run Code Online (Sandbox Code Playgroud)

lengthFold :: [a] -> Int
lengthFold xs = foldr (\_ y -> y+1) 0 xs
Run Code Online (Sandbox Code Playgroud)

它们是相同的,除了一个使用foldr和一个foldl.

但是当试图计算任何列表的长度时,[1 .. n]我从lengthFoldl得到了错误的结果(一个太大).

chi*_*chi 5

为了补充joelfischerr的答案,我想指出你的函数类型给出了一个提示.

lengthFoldl :: [Int] -> Int
lengthFold :: [a] -> Int
Run Code Online (Sandbox Code Playgroud)

他们为什么不同?我猜你可能不得不改变第一个,[Int]因为[a]它没有编译.然而这是一个很大的警示标志!

如果确实在计算长度,为什么要lengthFoldl关心列表元素的类型是什么?为什么我们需要元素为Ints?只需要一种可能的解释Int:查看代码

lengthFoldl xs = foldl (\_ y -> y+1) 0 xs
Run Code Online (Sandbox Code Playgroud)

我们可以看到这里唯一的数字变量是y.如果y被强制为数字,并且列表元素也被强制为数字,则好像y被视为列表元素!

事实确实如此:foldl首先将累加器传递给函数,将列表元素传递给第二个,不像foldr.

一般的拇指规则是:当类型和代码不一致时,应该仔细考虑哪一个是正确的.我会说大多数Haskellers会认为,在大多数情况下,比正确的代码更容易获得正确的类型.因此,不应该只是将类型调整为代码以强制它编译:类型错误可以反而见证代码中的错误.