Структури даних у функціональному програмуванні


11

В даний час я граю з LISP (зокрема, Scheme та Clojure) і мені цікаво, як типові структури даних обробляються у функціональних мовах програмування.

Наприклад, скажімо, що я хотів би вирішити проблему, використовуючи алгоритм графічного нанесення графіків. Як ти зазвичай можеш представити цей графік у функціональній мові програмування (насамперед цікавий чистий функціональний стиль, який можна застосувати до LISP)? Я б просто забув про графіки взагалі і вирішив проблему іншим способом?

Відповіді:


14

Минув час, коли я працював у LISP, але, як я пам’ятаю, основна неатомна структура - це список. Все інше базується на цьому. Таким чином, у вас може бути список атомів, де кожен атом - це вузол, а потім список ребер, які з'єднують вузол з іншими вузлами. Я впевнений, що є й інші способи зробити це.

Можливо, щось подібне:

(
  (a (b c)),
  (b (a c)),
  (c (a b d)),
  (d (c))
)

може дати такий графік:

a <--> b <--> c <--> d
^ ^
| |
+ --------- +

Якщо ви хочете пофантазувати, можете також додати ваги:

(
  (a (b 1.0 c 2.0)),
  (b (a 1.0 c 1.0)),
  (c (a 1.3 b 7.2 d 10.5)),
  (d (c -10.5))
)

Можливо, вас також зацікавить це: CL-Graph (знайдений Google-пошуком фрази "структура графіка lisp")


4
Це трохи пізно, але я думаю, що я повинен попередити, що "Все інше базується на [списку]" вводить в оману. Загальні Lisp, Scheme та Clojure - всі вектори, карти, рядки, а також структури / класи, не побудовані вгорі списків; код ми пишемо , щоб створити їх в цілому список, наприклад , (марка-масив «(2 + 2): початково-елемент 0), але структура даних не реалізовані з використанням списків.
coredump

3

Функціональні мови поводяться з структурами даних так само, як це роблять нефункціональні мови: шляхом відділення інтерфейсу від реалізації, створення абстрактних типів даних.

Ви можете створити абстрактні типи даних у Lisp. Наприклад, для графіка вам може знадобитися кілька функцій:

(define (get-vertices graph) ;; gets all the vertices from a graph
  ...)

(define (get-edges graph) ;; gets all the edges from a graph
  ...)

(define (get-weight vertex-from vertex-to) ;; get the weight of a specific vertex
  ...)

Після створення інтерфейсу для графіку ви можете реалізувати фактичні структури даних різними способами, можливо оптимізуючи такі фактори, як ефективність програміста, гнучкість та обчислювальна ефективність.

Ключ , щоб переконатися , що код , який використовує графіки тільки використовує інтерфейс графа, і не має доступу до основної реалізації. Це дозволить зробити код клієнта простішим, оскільки його не від'єднати від реальної реалізації.


2

Добре, це залежатиме від того, чи ваш графік спрямований / непрямий, зважений / невагомий, але один із способів представити спрямований, зважений графік (який був би найзагальнішим) - це карта карт (у Clojure)

{
 :a {:b 3 :c 4} 
 :b {:a 1} 
 :c {}
}

являє собою карту з вузлами: a: b і: c. : бали до: b з вагою 3 і: c з вагою 4: b вказує на: a з вагою 1.: c не вказує ні на що.


1

У Common Lisp, якщо мені потрібно було представити дерево, я б використав або список (якщо це був лише швидкий злом) або визначити клас дерева (або структура, але класи добре взаємодіють із загальними функціями, то чому б ні) .

(defclass tree ()
  ((node :accessor node :initarg :node)
   (children :accessor children :initarg :children)))

Якщо мені потрібні буквальні дерева в коді, я, мабуть, також визначив make-treeфункцію, яка бере список списку потрібного дерева і перетворює його в дерево дерев-об’єктів.


-2

У списку Haskell перелік є базовою структурою даних, і якщо ви хочете більш вдосконаленої структури даних, ви часто використовуєте рекурсивні структури, як дерево - нулеве, або вузол, і два дерева

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