Які існують типи алгебраїчних даних?


16

Я читаю про типи даних з алгебраїкою (завдяки Ричарду Мінериху я це знайшов чудове пояснення концепції). Хоча я думаю, що я розумію поняття типів суми та типів продуктів і т. Д., Я не зовсім розумію, наскільки алгебраїчні типи даних є корисними за межами уточнення відповідності шаблонів. Які ще речі можна зробити, якщо ADT не відповідає узорності?


EDIT: Я не запитую, що може робити розробник з ADT, що неможливо зробити з об'єктами. Я запитую, чи є інші операції, які дозволяють ADT; наприклад, чи можна зробити додаткові міркування щодо типів, що стосуються, якщо використовуються ADT? Чи сприяє ADT якийсь аналіз типу, який без них був би неможливим?


2
Що ви можете зробити з об'єктами, крім методів виклику?

1
ADT насправді означає "абстрактний тип даних", а не алгебраїчні типи даних.
Рейн Генріхс

4
@Rein: Це може посилатися на будь-який залежно від контексту.
sepp2k

4
@Rein: Це дійсно (що мені здається несподіваним, якщо чесно): Однак у статті вікіпедії для ADT перераховані як абстрактний тип даних, так і алгебраїчний тип даних, як можливі значення. ADT дуже часто використовується як абревіатура для алгебраїчних типів даних, наприклад, списку розсилки Haskell та каналу IRC.
sepp2k

1
@Rein, я знаю - я просто втомився вводити "Алгебраїчний тип даних" знову і знову, і я зрозумів, що люди зможуть зрозуміти, про що я маю на увазі контекст.
Оноріо Катенач

Відповіді:


10

Алгебраїчні типи даних відрізняються тим, що їх можна побудувати з декількох типів "речей". Наприклад, Дерево не може містити нічого (порожнє), листя або вузол.

data Tree = Empty
          | Leaf Int
          | Node Tree Tree

Оскільки Вузол складається з двох Дерев, алгебраїчні типи даних можуть бути рекурсивними.

Відповідність шаблонів дозволяє деконструювати алгебраїчні типи даних таким чином, щоб підтримувати безпеку типу. Розглянемо таку реалізацію глибини та її еквівалент псевдокоду:

depth :: Tree -> Int
depth Empty = 0
depth (Leaf n) = 1
depth (Node l r) = 1 + max (depth l) (depth r)

у порівнянні з:

switch on (data.constructor)
  case Empty:
    return 0
  case Leaf:
    return 1
  case Node:
    let l = data.field1
    let r = data.field2
    return 1 + max (depth l) (depth r)

Це має той недолік, що програміст повинен пам’ятати, що він видав порожнє перед Leaf, щоб поле1 не було доступно до порожнього дерева. Аналогічно, випадок Leaf повинен бути оголошений перед випадком Node, щоб поле2 не було доступно до Leaf. Таким чином, безпека типу не підтримується мовою, а накладає додаткове пізнавальне навантаження на програміста. До речі, я захоплюю ці приклади безпосередньо зі сторінок вікіпедії.

Звичайно, мовник, що набирає качку, може зробити щось подібне:

class Empty
  def depth
    0
  end
end

class Leaf
  def depth
    1
  end
end

class Node
  attr_accessor :field1, :field2

  def depth
    1 + [field1.depth, field2.depth].max
  end
end

Так що алгебраїчні типи даних можуть не бути суворо кращими, ніж їх еквівалент OOP, але вони створюють інший набір напруг, з якими можна працювати при створенні програмного забезпечення.


9

Я не дуже впевнений, що пояснення все таке чудове.

Алгебраїчні типи даних використовуються для створення структур даних, таких як списки та дерева.

Наприклад, дерева розбору легко представлені алгебраїчними структурами даних.

data BinOperator = Add
                 | Subtr
                 | Div
                 | Mult
                 | Mod
                 | Eq
                 | NotEq
                 | GreaterThan
                 | LogicAnd
                 | LogicOr
                 | BitAnd
                 | BitOr
                 | ...

data UnOperator = Negate
                | Not
                | Increment
                | Decrement
                | Complement
                | Ref
                | DeRef


data Expression = Empty
                | IntConst Int
                | FloatConst Float
                | StringConst String
                | Ident String
                | BinOp BinOperator Expression Expression
                | UnOp UnOperator Expression Bool //prefix or not
                | If Expression Expression Expression
                | While Expression Expression Bool //while vs. do while
                | Block List<Expression>
                | Call Expression List<Expression>
                | ...

Насправді не потрібно було б набагато більше представляти мову С.

Але дійсно, ви можете зробити що-небудь з алгебраїчними типами даних. Lisp доводить, що ви можете робити все з парами та ADT, просто забезпечити більш детальний та безпечний спосіб до цього підходу.

Звичайно, якщо ви запитаєте: "Що ви можете зробити з ADT, що ви не можете робити з об'єктами?", Відповідь - "нічого". Тільки іноді (здебільшого) ви знайдете рішення на ADT значно менші, ніж ті, що базуються на об'єктах, можливо, більш гнучкі. Отже, щоб розмістити його в дереві розбору, представленому ADT:

If(Call(Ident('likes_ADTs'),[Ident('you')]),
   Call(Ident('use_ADTs'),[Ident('you')]),
   Call(Ident('use_no_ADTs'),[Ident('you')]))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.