15

Ngôn ngữ nào không chỉ có chức năng có dữ liệu đại số loại (hoặc một cái gì đó tương tự) và khớp mẫu? Tôi cũng quan tâm đến các ngôn ngữ đa mô hình - tôi biết rằng Ocaml và F # là phương ngữ ML với OO được thêm vào, vì vậy chúng kế thừa các kiểu dữ liệu đại số từ ML.Loại dữ liệu đại số ngoài các ngôn ngữ chức năng?

Chúng có thể được mô phỏng bằng cách sử dụng enum s và union s (như trong C, C++, ... nhiều hơn?), Nhưng điều này sẽ trở nên cồng kềnh và xấu xí, và trình biên dịch không thể cảnh báo bạn nếu bạn quên một trường hợp phù hợp với mô hình của bạn hoặc (nhiều khả năng hơn, và nguy hiểm hơn nhiều) khi truy cập công đoàn "theo cách sai", nghĩa là bạn yêu cầu một trường có giá trị Left khi giá trị thực sự là giá trị Right (những gì bạn nhận được sau đó là sự giải thích vô nghĩa của các bit xảy ra ở đó).

Tôi đã nghe nói rằng Pascal has something like tagged unionsCyclone language cũng hỗ trợ công đoàn được gắn thẻ. Wikipedia cũng đề cập đến Ada và Algol. Bất kỳ ngôn ngữ nào khác?

(Trong trường hợp bạn chưa bao giờ nghe nói về các loại dữ liệu đại số, bạn có thể đọc an Answer to "What is 'Pattern Matching' in functional languages?" để có phần giới thiệu tuyệt vời).

Trả lời

13

Trong Scala, bạn thường sử dụng case class es để mô phỏng các kiểu dữ liệu đại số như được tìm thấy trong các ngôn ngữ chức năng thực sự màu xanh như ML và Haskell.

Ví dụ, sau F # mã (lấy từ 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 

có thể được tạm dịch sang Scala như sau:

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 
} 

Các sealed từ khóa trên được sử dụng để có trình biên dịch cảnh báo trong trường hợp bạn quên bất kỳ case nào trong biểu thức match.

6

Erlang có một hệ thống kiểu năng động, vì vậy nó không cung cấp bất kỳ bảo đảm bạn trích dẫn, nhưng Erlang mã này có xu hướng trông giống như sản phẩm của một hệ thống kiểu đại số:

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

length({rect, X, Y}) -> math:sqrt(X*X + Y*Y); 
length({polar, R, _A}) -> R. 
8

Các lập trình logic ngôn ngữ Mercury gọi chúng là discriminated unions. Ngôn ngữ ràng buộc CHR, được nhúng trong Prolog, has them cũng vậy, nhưng ở đó chúng hoàn toàn không bắt buộc, các thuật ngữ Prolog chung là kiểu mặc định.

+0

Cảm ơn - Tôi không biết ngôn ngữ logic, vì vậy tôi có thể không tự mình học được điều này. – delnan

+0

Cả hai đều là ngôn ngữ nghiên cứu. Cộng đồng LP đã vay mượn rất nhiều từ những người anh em họ FP của họ. –

10

Trong ngôn ngữ Rust của Mozilla, các loại dữ liệu đại số và đối sánh mẫu là các khái niệm quan trọng. Cú pháp cũng khá đẹp. Xem xét chương trình đơn giản sau đây:

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); 
} 
+1

Cú pháp cũng khá đẹp - vâng, ngoại trừ món xà lách xoăn và dấu chấm phẩy. – Ingo

+8

Niềng răng xoăn thật tuyệt vời. – Malcolm

+0

@Malcolm Tôi muốn downvote bình luận của bạn;) --- hiếm khi là quá nhiều tiếng ồn hữu ích, các niềng răng thậm chí không thông tin về những gì khối họ đóng! Phong cách cũ của if..fi hoặc do..od hoặc beginX ... endX ít nhất là thông tin, với niềng răng chúng ta có xu hướng kết thúc với một cầu thang chiếm không gian và hoàn toàn không hữu ích cho khả năng đọc .. –

3

Tôi nghĩ rằng Whiley sẽ đủ điều kiện. Mặc dù có các loại bản ghi (sản phẩm .ie) và các công đoàn loại (tức là tổng hợp), do đó.

Kết hợp dường như chỉ có thể trên loại, nghĩa là bạn có thể hỏi giá trị có loại công đoàn là một trong các loại trong liên minh và sau đó giá trị "được nhập lại" và bạn có thể truy cập vào các trường bạn đã kiểm tra.

Các vấn đề liên quan