head и tail в списках различий в Haskell, а-ля LYAH

Learn You a Haskell упоминает списков различий (поиск этого термина на этой странице), где список 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 ?

  1. Что вообще значит спросить, выполняется ли это в постоянное время, учитывая, что список различий является функцией, а не фактическим "значение"?
  2. Выполняется ли headTailDifList в постоянное время?
  3. Есть ли другая реализация с постоянным временем? Вот кандидат:

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

    Однако хвостовая часть не генерирует исключение, если dl равно id (пустой список различий).

11
задан Prateek 30 November 2011 в 14:40
поделиться