基本上,天真的算法使用附加。最初的回答。
revList [] = []
revList (x:xs) = revList xs ++ [x]
由于添加操作是一个O(n)的操作,其中n是++运算符的第一个(左)参数的长度,因此效率低下。因此,上面的revList函数最终变成了O(n(n-1)/2) ~ O(n^2)。
因此,在这样的追加任务中,有差异列表数据类型。
差异列表只是一个表示为函数的列表。我的意思是,当用DList类型表示类似于[1,2,3]
的列表时,它将是\xs -> [1,2,3] ++ xs
或简写为([1,2,3] ++)
。
Original Answer翻译成"最初的回答"
type DList a = [a] -> [a]
toDList :: [a] -> DList a
toDList xs = (xs ++ )
fromDList :: DList a -> [a]
fromDList f = f []
这很酷,因为DLists是函数,我们可以通过组合(.)运算符附加它们并获得一个新的DList。换句话说,
toDList (xs ++ ys) == (toDList xs) . (toDList ys)
。
那么这有什么用呢?通过使用嵌套函数组合,我们可以以类似于
revList
函数的方式反转列表,但成本要少得多。只有O(n),因为每个函数组合都是O(1)。
最初的回答:DLists是函数,可以通过组合运算符将它们附加到一起,形成新的DList。这种方法可以用于反转列表,并且成本较低,只需O(n)。
revList' :: [a] -> DList a
revList' [] = toDList []
revList' (x:xs) = revList' xs . toDList [x]
现在我们已经有了反转的
[a]
,在
DList a
类型中,我们只需要应用
fromDList
即可。"Original Answer"翻译成"最初的答案"。
fastReverse :: [a] -> [a]
fastReverse = fromDList . revList'
差异列表数据类型并不像我上面展示的那样简单。它可以有Monoid,Functor和MonadT实例。关于这个有用的数据类型的更多信息,请查看
Data.DList。最初的回答。
1:[2,3,4]
但是你不能做[2,3,4]:1
。在这个数组构造指令中,最左边的项要求该项为元素而不是数组。这是Haskell在这种情况下的方式,也是新手像我非常重要的核心概念,需要内化并适应。 - daparic