Алгебраические типы данных за пределами функциональных языков?
Вопрос
Какие языки, которые не являются исключительными функциональными типами, имеют алгебраические типы данных (или что-то подобное) и сопоставление шаблонов? Я также заинтересован в мульти-парадигме языков - я знаю, что OCAML и F # представляют собой ML диалекты с добавленными OO OO, поэтому они наследуют алгебраические типы данных из ML.
Они могут быть добрыми эмулируемыми, используя enum
песок union
S (как в C, C ++, ... больше?), Но вскоре это становится громоздким и уродливым, и компилятор не может предупредить вас, если вы забудете дело в соответствии с сопоставлением или (гораздо более прогрессированным и гораздо более опасным ) при доступе к союзу «неправильно», то есть вы просите поле Left
ценность, когда это на самом деле Right
Значение (то, что вы получаете, это бессмысленное реинтерпретация битов, которые будут там).
Я слышал это Паскаль имеет что-то вроде помеченных союзов и то Язык циклона Поддерживает помеченные профсоюзы тоже. Википедия также упоминает ADA и ALGOL. Любые другие языки?
(Если вы никогда не слышали об алгебраических типах данных, вы можете прочитать Ответ на «Что такое» сопоставление картины «в функциональных языках?» Для отличного введения).
Решение
В 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
выражение.
Другие советы
В Мозилсе Ржавчина Язык, алгебраические типы данных и сопоставление картины являются важными концепциями. Синтаксис также довольно хороший. Рассмотрим следующую простую программу:
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);
}
Логический язык программирования Mercury вызывает их дискриминированные союзы. Отказ Язык ограничения Chr, встроенный в пролог, имеет их ТОО, но там они совершенно необязательны, общий пролог, являющийся типом по умолчанию.
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.
я думаю что Пока будет иметь право. В то время как есть типы записи (.ie. Продукт) и профсоюзами типа (т. Е. Сумма), следовательно,.
Соответствие, кажется, возможна только на типе, то есть вы можете спросить, является ли значение с типом Union Type одним из типов в Union, а затем значение «повторно набрано», и вы можете получить доступ к полям типа, который вы проверили.