函数式语言之外的代数数据类型?

时间:2010-10-18 20:18:48

标签: language-agnostic programming-languages functional-programming algebraic-data-types

哪些语言不仅仅具有代数数据 类型(或类似的东西)和模式匹配?我也对多范式语言感兴趣 - 我知道Ocaml和F#是添加了OO的ML方言,所以它们继承了ML的代数数据类型。

它们可以使用enumunion进行模拟(如C,C ++,...更多?),但这很快变得麻烦和丑陋,编译器可以当你以“错误的方式”访问联合时,如果你在模式匹配中忘记了一个案例或者(更可行,更危险),那就警告你了,即你要求一个Left值的字段。实际上是一个Right值(你得到的是对那些恰好存在的位的无意义的重新解释)。

我听说Pascal has something like tagged unionsCyclone language也支持带标记的联盟。维基百科还提到了阿达和阿尔戈尔。还有其他任何语言吗?

(如果您从未听说过代数数据类型,可以阅读an Answer to "What is 'Pattern Matching' in functional languages?"以获得精彩的介绍。)

5 个答案:

答案 0 :(得分:13)

在Scala中,您通常使用case class es来模拟像ML和Haskell这样的真蓝色函数语言中的代数数据类型。

例如,遵循F#代码(取自here):

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

答案 1 :(得分:10)

在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);
}

答案 2 :(得分:8)

Mercury称之为discriminated unions的逻辑编程语言。约束语言CHR,也嵌入在Prolog中,has them,但它们完全是可选的,一般的Prolog术语是默认类型。

答案 3 :(得分:6)

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.

答案 4 :(得分:3)

我认为Whiley符合资格。 因此,虽然有记录类型(.ie。产品)和类型联合(即总和)。

匹配似乎只能在类型上进行,即你可以询问具有union类型的值是否是union中的类型之一,然后值是“re-typed”,你可以访问类型的字段你检查。