Я хотів би дізнатися, як скласти графіки та виконувати деякі локальні операції над ними в Haskell, але питання не є специфічним для Haskell, і замість графіків ми можемо розглядати подвійно пов'язані списки.
Запитання: Який би був ідіоматичний чи рекомендований спосіб впровадження подвійно пов'язаного списку (або іншої подвійно пов'язаної чи кругової структури даних) та операцій над ним мовою, яка в основному підтримує та виступає за незмінні структури даних (Haskell, Clojure тощо) ? Зокрема, як використовувати оновлення на місці, які формально заборонені мовою?
Я легко можу уявити, що якщо якась локальна операція виконується у подвійному зв’язку списку (якщо елемент вставляється, наприклад), можливо, не буде необхідності негайно копіювати весь список через лінь мови. Однак, оскільки список подвійно пов'язаний, якщо його змінити в одному місці, жоден із старих вузлів не може бути використаний у новій версії списку, і їх потрібно було якось позначити, скопіювати, зібрати сміття рано чи пізно . Очевидно, що це зайві операції, якщо використовуватиметься лише оновлена копія списку, але вони додадуть "накладні витрати", пропорційні розміру списку.
Чи означає це, що для таких завдань незмінні дані просто недоречні, а функціональні декларативні мови без "рідної" підтримки змінних даних не такі гарні, як імперативні? Або є якийсь хитрий спосіб вирішення?
PS Я знайшов деякі статті та презентації на цю тему в Інтернеті, але важко дотримувався їх, в той час як я думаю, що відповідь на це питання не повинен мати більше одного абзацу, а може бути і діаграми ... Я маю на увазі, якщо є немає жодного "функціонального" рішення цієї проблеми, відповідь, ймовірно, "використовувати C". Якщо така є, то наскільки вона може бути складною?
Пов'язані питання
"Структури даних у функціональному програмуванні" . Моє конкретне питання щодо використання оновлень на місці замість неефективних альтернатив там не обговорюється.
"Внутрішня мутація стійких структур даних" . Здається, акцент робиться на низькому рівні реалізації не визначеної мови, тоді як моє питання стосується правильного вибору мови (функціональної чи іншої) та можливих ідіоматичних рішень у функціональних мовах.
Відповідні пропозиції
Суто функціональні мови програмування дозволяють висловити багато алгоритмів дуже стисло, але є кілька алгоритмів, в яких стан оновлених даних на місці, здається, відіграє вирішальну роль. Для цих алгоритмів суто функціональні мови, яким не вистачає стану оновлення, виявляються суттєво неефективними ( [Ponder, McGeer and Ng, 1988] ).
- Джон Ленбербері та Саймон Пейтон Джонс, "Ленті функціональних державних потоків" (1994), також Джон Ленбербері та Саймон Пейтон Джонс, штат Хаскелл (1995). Ці документи представляють ST
конструктор монадичного типу в Хаскеллі.
DiffArray
тип. Дивлячись на джерело з diffarray пакета, я бачу 91 входжень unsafePerformIO
. Схоже, відповідь на моє запитання: «так, ні, суто функціональні мови з незмінними даними не підходять для реалізації алгоритмів, які зазвичай покладаються на оновлення на місці».
Map
, IntMap
або HashMap
) як сховище і зробити так, щоб вузли містили ідентифікатори пов'язаних вузлів. "Усі проблеми з інформатики можна вирішити іншим рівнем непрямості".