Алгебраические типы данных вне функциональных языков? - PullRequest
15 голосов
/ 19 октября 2010

Какие языки, которые не являются исключительно функциональными, имеют алгебраические типы данных (или что-то подобное) и сопоставление с образцом?Мне также интересны мультипарадигмальные языки - я знаю, что Ocaml и F # - это диалекты ML с добавленным OO, поэтому они наследуют алгебраические типы данных от ML.

Их можно эмулировать с помощью enum s и union s (как в C, C ++, ... еще?), но это скоро становится громоздким и уродливым, и компилятор не может предупредить вас, если вы забудете случай в сопоставлении с шаблоном или (намного больше)вероятно, и гораздо более опасно) при доступе к объединению «неправильными способами», т.е. вы запрашиваете поле со значением Left, когда оно на самом деле является значением Right (тогда вы получаете бессмысленную реинтерпретацию битов, которыечто-то там есть).

Я слышал, что В Паскале есть что-то вроде теговых союзов , а Cyclone language также поддерживает теговые союзы.В Википедии также упоминаются Ада и Алгол.Любые другие языки?

(Если вы никогда не слышали об алгебраических типах данных, вы можете прочитать Ответ на вопрос «Что такое 'Pattern Matching' в функциональных языках?" для отличного введения).

Ответы [ 5 ]

13 голосов
/ 19 октября 2010

В Scala вы обычно используете case class es для эмуляции алгебраических типов данных, которые можно найти в функциональных языках истинно синего цвета, таких как ML и Haskell.

Например, следующий код F # (взятый из здесь ):

type Shape =
| Circle of float
| EquilateralTriangle of double
| Square of double
| Rectangle of double * double

let area myShape =
    match myShape with
    | Circle radius -> Math.PI * radius * radius
    | EquilateralTriangle s -> (sqrt 3.0) / 4.0 * s * s
    | Square s -> s * s
    | Rectangle (h, w) -> h * w

можно примерно перевести на Scala следующим образом:

sealed abstract class Shape
case class Circle(radius: Float) extends Shape
case class EquilateralTriangle(side: Double) extends Shape
case class Square(side: Double) extends Shape
case class Rectangle(height: Double, width: Double) extends Shape

def area(myShape: Shape) = myShape match {
  case Circle(radius) => math.Pi * radius * radius
  case EquilateralTriangle(s) => math.sqrt(3.0) / 4.0 * s * s
  case Square(s) => s * s
  case Rectangle(h, w) => h * w
}

Приведенное выше ключевое слово sealed используется, чтобы компилятор предупреждал вас в случае, если вы забудете какой-либо case в выражении match.

10 голосов
/ 18 января 2013

В языке Mozilla Rust алгебраические типы данных и сопоставление с образцом являются важными понятиями.Синтаксис также довольно приятный.Рассмотрим следующую простую программу:

static PI: f32 = 3.14159;

enum Shape {
    Circle(f32),
    Rectangle(f32, f32),
    Point
}

fn area(shape: Shape) -> f32 {
    match shape {
        Point                    => 0.0
        Circle(radius)           => PI * radius * radius,
        Rectangle(width, height) => width * height,
    }
}

fn main() {
    let radius = 4.0;
    let circle = Circle(radius);
    let area = area(circle);
    println!("The area of a circle with radius {} is {}", radius, area);
}
8 голосов
/ 19 октября 2010

Язык логического программирования Меркурий называет их различимыми союзами .Язык ограничений CHR, встроенный в Prolog, также имеет их , но там они являются полностью необязательными, общие термины Prolog являются типом по умолчанию.

6 голосов
/ 19 октября 2010

Erlang имеет динамическую систему типов, поэтому он не предоставляет никаких гарантий, которые вы цитируете, но код Erlang действительно имеет тенденцию выглядеть как продукт системы алгебраических типов:

count([]) -> 0;
count([H|T]) -> 1 + count(T).

length({rect, X, Y}) -> math:sqrt(X*X + Y*Y);
length({polar, R, _A}) -> R.
3 голосов
/ 31 июля 2013

Я думаю, что Пока подойдет. В то время как уyy есть типы записей (.ie. Product) и объединения типов (т.е. sum), следовательно.

Сопоставление представляется возможным только для типа, т. Е. Вы можете спросить, является ли значение с типом объединения одним из типов в объединении, а затем значение «перепечатано» и получить доступ к полям типа проверено на.

...