Переліки відмінностей у функціональному програмуванні


14

Питання Що нового в чисто функціональних структурах даних після Окасакі? , і епічна відповідь jbapple, згадана з використанням списків різниць у функціональному програмуванні (на відміну від логічного програмування), що мене нещодавно цікавило. Це змусило мене знайти реалізацію списку різниць для Haskell. У мене є два запитання (пробачте / виправте мене, якщо я повинен зробити їм два різні запитання на StackExchange).

Просте запитання полягає в тому, чи хтось знає про академічне врахування різницьких списків у функціональному програмуванні та / або реалізаціях, окрім списку в бібліотеці Haskell? Відповідь jbapple не дала цитування для різницьких списків (різницькі списки в логічному програмуванні існують у кращому і в декількох джерелах, які я маю Around Here Somewhere (TM)). Перш ніж знайти реалізацію Haskell, я не знав, що ідея перейшла від логіки до функціонального програмування. Звичайно, списки різниці Haskell є чимось природним використанням функцій вищого порядку і працюють зовсім інакше, ніж в логічному програмуванні, але інтерфейс, безумовно, схожий.

Більш цікава (і куди більш нечітка) річ, про яку я хотів запитати, - чи здається, що заявлена ​​асимптотична верхня межа для вищезгаданої бібліотеки списку різниць Хаскеля видається правильною / правдоподібною. Моя плутанина може бути через те, що я пропускаю щось із очевидним щодо аргументації складності з лінню, але заявлені межі мають сенс для мене, лише якщо заміна на велику структуру даних (або формування закриття, або змінний пошук, або щось таке ) завжди потребує постійного часу. Або "улов" просто у тому, що немає часу для "голови" та "хвоста", не пов'язаного саме з тим, що ці операції, можливо, доведеться орати через довільну купу відкладених обчислень / підстановок?


1
Спочатку мене бентежили "функціональні мови програмування (на відміну від функціональних мов програмування)", але ти мав на увазі написати "(на відміну від мов логічного програмування)"?
Tsuyoshi Ito

Ой, ой, так, це я мав на увазі, це зараз виправлено.
Роб Сіммонс

Друге питання здається мені більш підходящим щодо Stack Overflow, але тепер, коли ви його тут задали, може бути краще почекати, щоб дізнатись, чи хтось може відповісти тут. Особисто я не можу знайти жодних причин сумніватися у заявлених межах прочитання вихідного коду, але я не дотримувався ваших міркувань, щоб сумніватися в них, а також я можу щось пропустити.
Tsuyoshi Ito

Відповіді:


9

Або "улов" просто у тому, що немає часу для "голови" та "хвоста", не пов'язаного саме з тим, що ці операції, можливо, доведеться орати через довільну купу відкладених обчислень / підстановок?

Θ(m)m

O(1) fromList

{-# LANGUAGE NoMonomorphismRestriction #-}

data DL a = Id
          | Cons a
          | Compose (DL a) (DL a)

fromList [] = Id
fromList (x:xs) = Compose (Cons x) (fromList xs)

toList x = help x []
    where help Id r = r
          help (Cons a) r = a:r
          help (Compose f g) r = help f $ help g r

empty = Id

singleton = Cons

cons x = append (singleton x)

append = Compose

snoc xs x = append xs (singleton x)

Θ(n)headtail[a] -> [a]toList


Тож те, що ти отримуєш від лінощів, - це лише те, що запит на хвіст списку двічі не зробить дорогу операцію двічі, що приємно.
Роб Сіммонс

@Rob, я не розумію, що ти маєш на увазі під цим.
jbapple

Я думаю, що пункт, який я намагався зробити (погано), проілюстрований на цьому прикладі: у мене надзвичайно довгий перелік різниць "xs", який я робив, повторюючи "заношування" речей до оригінального списку. Перший раз, коли я називаю "head xs", я сподіваюся, що знадобиться O (n) час, щоб зробити відкладені обчислення; однак, оскільки це обчислення має бути запам'ятоване, другий виклик "head xs" (для тих же "xs") повинен зайняти O (1) час.
Роб Сіммонс

1
Ну, я з цим згоден, але лінь, на яку я посилався у своїй відповіді, стосувалась списку, який не використовується в snoc або head. Отож, педантичний, як це є, мене збентежило "що" у вашому висловленні, "що ви отримуєте від лінощів". Я б сказав, що ваш приклад і моє - це дві речі, які ви отримуєте від ліні.
jbapple

Гаразд - і це уточнення допомагає мені краще зрозуміти і ваш попередній пункт.
Роб Сіммонс

12

Так, межі залежать від припущення, що склад функції займає постійний час. В основному, якщо у вас є список приєднання:

datatype 'a join = Nil | Cons of 'a * 'a join | Join of 'a join * 'a join

O(n)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.