Haskell,àlaLYAH的不同名单上的头尾

时间:2011-11-30 14:40:59

标签: list haskell lazy-evaluation

向您学习Haskell提及difference lists(在该页面上搜索此术语),其中列表l不是直接表示,而是作为函数(l++)表示。这允许左右两侧更有效的连接。连接成为函数组合,最终可以通过($[])转换为真实列表。我想知道哪些操作可以在差异列表上有效支持。例如,差异列表的等效(:)

\x l -> (x:) . l

可以为差异列表高效实施headtail吗?这是明显的实现:

headTailDifList :: ([a] -> [a]) -> (a, [a] -> [a])
headTailDifList dl = (head l, ((tail l)++))
    where
    l = dl []

对于真实列表,\l -> (head l, tail l)以恒定时间运行。那headTailDifList怎么样?也许由于懒惰的评估,只会评估l的第一个元素?

  1. 如果差异列表是一个函数而不是一个实际的“值”,那么询问它是否会在恒定时间运行甚至是什么意思?
  2. headTailDifList是否会在恒定时间内运行?
  3. 还有其他一些常量时间实现吗?这是一个候选人:

    headTailDifList dl = (head (dl []), tail.dl )
    

    但是,如果dlid(空差异列表),则尾部不会抛出异常。

1 个答案:

答案 0 :(得分:3)

查看dlist包,它提供了差异列表的典型实现。它定义了类型DList

newtype DList a = DL { unDL :: [a] -> [a] }

以及所有常见的列表函数,包括headtail

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所指出的,只是生成第一个元素可能会在不变的时间内完成。