15

¿Qué idiomas que no son únicamente funcionales tienen datos algebraicos tipos (o algo similar) y coincidencia de patrón? También me interesan los lenguajes multi-paradigma: sé que Ocaml y F # son dialectos ML con OO agregado, por lo que heredan los tipos de datos algebraicos de ML.Tipos de datos algebraicos fuera de los lenguajes funcionales?

Pueden ser de tipo de emulado usando enum s y union s (como en C, C++, ... más?), Pero pronto se pone incómodo y feo, y el compilador no le avisará si se olvida un caso en su coincidencia de patrón o (mucho más propagable y mucho más peligroso) al acceder a la unión "de maneras incorrectas", es decir, solicita un campo de un valor Left cuando en realidad es un valor Right (lo que obtiene entonces es un reinterpretación sin sentido de los bits que están allí).

He oído que Pascal has something like tagged unions y Cyclone language también admiten uniones etiquetadas. Wikipedia también menciona Ada y Algol. ¿Algún otro idioma?

(En caso de que nunca haya oído hablar de tipos de datos algebraicos, puede leer an Answer to "What is 'Pattern Matching' in functional languages?" para una introducción excelente).

Respuesta

13

En Scala, normalmente usaría case class es para emular los tipos de datos algebraicos que se encuentran en los idiomas funcionales verdaderos como ML y Haskell.

Por ejemplo, tras F # código (tomado de 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 

puede ser traducido aproximadamente a Scala como sigue:

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 
} 

El sealed palabra clave anterior se usa para tener el compilador advertir en caso de que olvide cualquier case en la expresión match.

6

Erlang tiene un sistema de tipo dinámico, por lo que no proporciona ninguna de las garantías que usted cita, pero el código Erlang tiende a parecerse al producto de un sistema de tipo algebraico:

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

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

La programación lógica el lenguaje Mercury los llama discriminated unions. El idioma de restricción CHR, incrustado en Prolog, has them también, pero allí son totalmente opcionales, los términos generales de Prolog son del tipo predeterminado.

+0

Gracias - No tengo ni idea de los lenguajes lógicos, por lo que seguramente no lo habría aprendido. – delnan

+0

Ambos son lenguajes de investigación. La comunidad LP ha estado pidiendo prestado mucho a sus primos FP. –

10

En el lenguaje Rust de Mozilla, los tipos de datos algebraicos y la coincidencia de patrones son conceptos importantes. La sintaxis también es bastante agradable. Considere el siguiente programa simple:

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

La sintaxis también es bastante buena, sí, a excepción de la ensalada de llaves y el punto y coma. – Ingo

+8

Las llaves son geniales. – Malcolm

+0

@Malcolm Quiero desestimar su comentario;) --- rara vez es excesivo el ruido útil, los refuerzos ni siquiera son informativos de qué bloque se cierran! El viejo estilo de if..fi o do..od o beginX ... endX al menos es informativo, con llaves tienden a terminar con una escalera que ocupa espacio y es completamente inútil para la legibilidad .. –

3

Creo que Whiley calificaría. Whiley tiene tipos de registro (es decir, producto) y escribe uniones (es decir, suma), por lo tanto.

La coincidencia parece posible solo en el tipo, es decir, puede preguntar si un valor con tipo de unión es uno de los tipos en la unión y luego el valor se "vuelve a escribir" y puede acceder a los campos del tipo usted revisó

Cuestiones relacionadas