向您学习Haskell提及difference lists(在该页面上搜索此术语),其中列表l
不是直接表示,而是作为函数(l++)
表示。这允许左右两侧更有效的连接。连接成为函数组合,最终可以通过($[])
转换为真实列表。我想知道哪些操作可以在差异列表上有效支持。例如,差异列表的等效(:)
为
\x l -> (x:) . l
可以为差异列表高效实施head
和tail
吗?这是明显的实现:
headTailDifList :: ([a] -> [a]) -> (a, [a] -> [a])
headTailDifList dl = (head l, ((tail l)++))
where
l = dl []
对于真实列表,\l -> (head l, tail l)
以恒定时间运行。那headTailDifList
怎么样?也许由于懒惰的评估,只会评估l
的第一个元素?
headTailDifList
是否会在恒定时间内运行?还有其他一些常量时间实现吗?这是一个候选人:
headTailDifList dl = (head (dl []), tail.dl )
但是,如果dl
为id
(空差异列表),则尾部不会抛出异常。
答案 0 :(得分:3)
查看dlist包,它提供了差异列表的典型实现。它定义了类型DList
:
newtype DList a = DL { unDL :: [a] -> [a] }
以及所有常见的列表函数,包括head
和tail
:
head :: DList a -> a
head = list (error "Data.DList.head: empty list") const
tail :: DList a -> DList a
tail = list (error "Data.DList.tail: empty list") (flip const)
此处,list
定义为:
list :: b -> (a -> DList a -> b) -> DList a -> b
list nill consit dl =
case toList dl of
[] -> nill
(x : xs) -> consit x (fromList xs)
使用:
fromList :: [a] -> DList a
fromList = DL . (++)
toList :: DList a -> [a]
toList = ($[]) . unDL
也就是说,list
花费O(n)时间来生成所有元素。正如JohnL所指出的,只是生成第一个元素可能会在不变的时间内完成。