如何在 Haskell 中编写反向函数

How to write a a reverse function in Haskell

所以,我知道,在 Haskell 中有一个用于反转列表的内置函数,但我正在尝试编写自己的小函数,只是为了练习一些 Haskell。我想到了以下代码,遗憾的是它不起作用。你们能告诉我我做错了什么吗?

    rev :: [Int] -> [Int]
    rev [] = []
    rev [x] = last [x] : rev init [x]

你几乎成功了。

rev :: [Int] -> [Int]
rev [] = []
rev x = last x : rev (init x)

解释:[x]是一个包含x的列表,而您想直接对x进行操作

ps。这是 documentation for Data.List。记得 import Data.List

嗯,你可以这样做:

rev :: [Int] -> [Int]
rev [] = []
rev (x:l) = (rev l) ++ [x]

第 3 行从列表中取出第一个元素,然后创建一个仅包含该元素的列表。这附加到递归 rev l 调用的结果。

如果你想高效地做到这一点,我建议你使用累加器:

rev :: [a] -> [a]
rev xs = go xs []
   where
   go :: [a] -> [a] -> [a]
   go []     ys = ys
   go (x:xs) ys = go xs (x:ys)

函数 go 在每一步中从第一个列表 xs 中删除一个元素并将其添加到第二个列表 ys 之前。这类似于从堆栈中弹出并推入另一个堆栈——顺序颠倒。

由于我们在每次递归调用中只使用固定的时间,所以我们得到 O(n) 的复杂度,其中 n 是列表长度。

相反,如果在每次递归调用中我们使用 last 或追加 ... ++ [x],我们为每次调用支付 O(n),因此整体 O(n^2)。