4

我正在学习haskell,我尝试在不使用递归的情况下编写自己的反向函数。

解决方案是这个功能:

myreverse = foldl (flip (:)) []

我试图了解在评估过程中会发生什么,比如:

myreverse [1..5]

我不明白翻转在这里做什么。有人可以通过一步一步的解释写下这里发生的事情吗?

4

2 回答 2

6

翻转相当容易:

如果你有一个函数f :: a -> b -> cthenflip f是一个函数:: b -> a -> c,所以它会给你一个新函数并翻转你必须传递的参数的顺序。

(:) :: a -> [a] -> [a]是这种模式的一个函数,因此flip (:)现在将是一个函数,它首先获取即将成为尾巴的尾部,然后是新的头部,并返回一个包含以下内容的新列表:

(flip (:)) [2..4] 1
= (:) 1 [2..4]
= 1 : [2..4]
= [1,2,3,4]

现在你需要这个,因为foldl它是这样定义的:

foldl :: (b -> a -> b) -> b -> [a] -> b

你看 - 你必须传递的函数将是一个首先接受一个列表,然后是一个元素并返回一个新列表的函数

这现在将全部折叠成这样的:

myreverse [1..5]
= foldl (flip (:)) [] [1,2,3,4,5]
= foldl (flip (:)) (((flip (:)) [] 1)) [2,3,4,5]
= foldl (flip (:)) (1:[]) [2,3,4,5]
= foldl (flip (:)) (((flip (:)) [1] 2)) [3,4,5]
= foldl (flip (:)) (2:[1]) [3,4,5]
= ...
= [5,4,3,2,1]
于 2015-05-21T09:44:12.367 回答
3

您可以尝试在 ghciflip中执行以下操作:

:t (:)
(:) 1 [2..4]

[1,2,3,4]

:t flip (:)
(flip (:)) [2..4] 1

[1,2,3,4]

于 2015-05-21T14:53:24.253 回答