15 language-agnostic programming-languages functional-programming algebraic-data-types
哪些不仅仅是功能性的语言具有代数数据类型(或类似的东西)和模式匹配?我也对多范式语言感兴趣 - 我知道Ocaml和F#是添加了OO的ML方言,因此它们继承了ML的代数数据类型.
它们可以使用enums和unions 进行模拟(如C,C++,...更多?),但这很快变得麻烦和丑陋,如果你在模式匹配中忘记了一个案例,编译器就无法发出警告或者(更可行,更危险)当以"错误的方式"访问联合时,即,Left当它实际上是一个值时,你要求一个值的字段Right(你得到的是对碰巧发生的那些位的无意义的重新解释)在那里).
我听说Pascal有类似标记的联合,而Cyclone语言也支持标记的联合.维基百科还提到了阿达和阿尔戈尔.还有其他语言吗?
(如果您从未听说过代数数据类型,您可以阅读函数式语言中"什么是'模式匹配'的答案?"以获得精彩的介绍.
mis*_*tor 13
在Scala中,您通常使用case classes来模拟真正的蓝色函数语言(如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
Run Code Online (Sandbox Code Playgroud)
可以粗略地翻译成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
}
Run Code Online (Sandbox Code Playgroud)
在sealed上述用于有编译器关键字发出警告的情况下,你忘记任何case在match表达式.
Vik*_*ahl 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);
}
Run Code Online (Sandbox Code Playgroud)
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.
Run Code Online (Sandbox Code Playgroud)