Language agnostic 函数语言之外的代数数据类型?
哪些不只是函数的语言有代数数据 类型(或类似的东西)和模式匹配?我还对多范式语言感兴趣——我知道Ocaml和F#是添加了OO的ML方言,因此它们继承了ML的代数数据类型 < >可以使用<代码> EnUM<代码> >和<代码>联合< /Calp> S(如C,C++,…更多)来模拟,但是这很快会变得麻烦和丑陋,如果你忘记了模式匹配的情况下,编译器不能警告你,或者当访问联盟“错误的方式”时,(更可支持,更危险)。也就是说,当字段实际上是Language agnostic 函数语言之外的代数数据类型?,language-agnostic,programming-languages,functional-programming,algebraic-data-types,Language Agnostic,Programming Languages,Functional Programming,Algebraic Data Types,哪些不只是函数的语言有代数数据 类型(或类似的东西)和模式匹配?我还对多范式语言感兴趣——我知道Ocaml和F#是添加了OO的ML方言,因此它们继承了ML的代数数据类型 < >可以使用 EnUM >和联合< /Calp> S(如C,C++,…更多)来模拟,但是这很快会变得麻烦和丑陋,如果你忘记了模式匹配的情况下,编译器不能警告你,或者当访问联盟“错误的方式”时,(更可支持,更危险)。也就是说,当字段实际上是右值时,您请求一个左值的字段(然后您得到的是对碰巧存在的位的无意义的重新解释) 我听说了,
右
值时,您请求一个左
值的字段(然后您得到的是对碰巧存在的位的无意义的重新解释)
我听说了,支持工会的人也这么说。维基百科也提到了Ada和Algol。还有其他语言吗
(如果您从未听说过代数数据类型,您可以阅读一篇精彩的介绍)。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.
逻辑编程语言Mercury调用它们。约束语言CHR也嵌入在Prolog中,但它们是完全可选的,一般的Prolog术语是默认类型。在Scala中,您通常会使用
case类
es来模拟在真正的蓝色函数语言(如ML和Haskell)中发现的代数数据类型
例如,以下F#代码(取自):
可以大致转换为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
关键字用于让编译器在您忘记match
表达式中的任何case
时向您发出警告。在Mozilla语言中,代数数据类型和模式匹配是重要的概念。语法也相当不错。考虑下面的简单程序:
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);
}
我想那是符合条件的。
Whiley有记录类型(.ie.乘积)和类型联合(即sum),因此
匹配似乎只能在类型上进行,即,您可以询问具有联合类型的值是否是联合中的一种类型,然后该值被“重新类型化”,您可以访问您检查的类型的字段。谢谢-我不知道逻辑语言,所以我可能自己不会学这个。这两种语言都是研究语言。LP社区从它的FP近亲那里借用了很多东西。语法也相当不错-是的,除了花括号和分号。@Malcolm我想否决你的评论;)---过大的噪音很少有帮助,大括号甚至不能说明它们关闭了哪个块!if..fi或do..od或beginX…endX的旧样式至少是信息型的,使用大括号,我们往往会以占用空间的楼梯结束,这对可读性完全没有帮助。使用自动代码格式,它们是信息型的。要确定哪个大括号与块相对应,只需在垂直线上查找页面。不管风格如何,理解范围的开始和结束都会带来认知开销。如果使用“beginX/endX”,则必须命名所有作用域,并按名称记住所有作用域,以导航代码段。这就是我所看到的增加噪音——额外的认知开销(命名范围),没有任何额外的好处。在看到一些Ada代码之前,我一直在考虑使用关键字创建代码块(如if、fi、begin、end)。大括号的优点是不会增加字符噪波。在阅读代码时,我们不仅希望代码在某种层次结构中得到明确定义(这就是我们缩进的原因),我们还希望我们的重点是创建什么,而不是一堆begin/end/procedure/等等。许多花括号语言的问题是,使用它们的语言鼓励使用具有许多嵌套控件特性的长函数。相反,该语言应该支持诸如第一类函数、类型推断(关于函数返回和参数)等,以鼓励更短的函数。
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);
}