在列表中的链接元素对上映射函数

Pab*_*blo 1 haskell functional-programming

我想在列表中的链式元素对上映射函数.考虑清单:

a = [1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)

通过使用例如函数f a1 a2 = a1 < a2,我想得到:

[True,True,True,True]
Run Code Online (Sandbox Code Playgroud)

以下似乎总体上起作用:

zipWith f a (tail a)
Run Code Online (Sandbox Code Playgroud)

但是,我发现它有点像hackish.有没有更合适的方式,也许使用折叠?

Thr*_*eFx 6

我想我可以代表Haskell社区发言,如果我告诉你这是在Haskell中这样做的最惯用的方式.你可以使用折叠一起破解某些东西,但它显然不像第一个变体那么可读:

f p xs = snd $ foldl (\acc x -> (x, snd acc ++ [p (fst acc) x])) (head xs, []) (tail xs)
Run Code Online (Sandbox Code Playgroud)

感谢@WillNess提供上述功能的更具可读性的版本,尽管它仍然没有zipWith简洁明了.

f p = foldr g [] . tails where g (x:y:_) r = p x y:r; g _ _ = []
Run Code Online (Sandbox Code Playgroud)

这真是个hackish.在这种情况下使用折叠的问题在于,通常元素将被单独处理,并且它们不"知道"它们的邻居.他们知道的唯一值是累加器和它们自己的值.

在这个例子中,做f (<) [1,2,3,4,5]会检查是否有对的左边元素比前一个更小,但它的方式不止做的可读性:

f p xs = zipWith p xs (tail xs)
Run Code Online (Sandbox Code Playgroud)

用法与上述相同.


请注意,我在Haskell语言中并不专业,因此使用折叠的这种方法可能是以更好的方式编写的,但是它永远不会超越方法的优雅zipWith.