ML (Meta Language) es el metalenguaje desarrollado para el demostrador de teoremas Edinburgh LCF en la década de 1970. Es un lenguaje funcional de tipado estático temprano con inferencia de tipos polimórfica al estilo Hindley-Milner , y otras características como excepciones y variables mutables . [ 1 ] El diseño de ML en LCF inspiró directamente a la posterior familia ML (en particular Standard ML , Caml y sus derivados) e influyó en el desarrollo posterior de lenguajes funcionales. [ 4 ]
Historia
ML comenzó a desarrollarse por Robin Milner a su llegada a la Universidad de Edimburgo en 1973 con la ayuda de los asistentes de investigación Lockwood Morris y Malcolm Newey, ambos postdoctorandos de Stanford que fueron contratados por Milner. [ 5 ] Michael Gordon , Christopher Wadsworth y otros estudiantes de posgrado se unieron a la investigación en 1975. [ 4 ] Históricamente, ML fue concebido para desarrollar tácticas de prueba en el demostrador de teoremas LCF y suceder a la iteración anterior Stanford LCF , tratando de resolver problemas relacionados con la utilización del espacio y la extensibilidad de la prueba. ML actuó como un metalenguaje (de ahí el nombre) y un lenguaje de comandos ( REPL ) para el sistema LCF . PPLAMBDA , un lenguaje que era conceptualmente una combinación del cálculo de predicados de primer orden y el cálculo lambda polimórfico simplemente tipado , fue el lenguaje subyacente en el que se construyeron más directamente los enunciados de teoremas. [ 1 ]
Mientras se desarrollaba ML, Milner escribió el artículo «Una teoría del polimorfismo de tipos en la programación» en 1978, que exponía las ideas sobre lo que significaba que un programa estuviera bien tipado en el contexto de un sistema de tipos polimórfico (genérico). Utilizó ML como caso práctico de aplicación de los teoremas desarrollados y señaló los desafíos teóricos que surgieron durante el desarrollo y que aún no se habían resuelto. [ 6 ] El diseño de la primera versión de ML se finalizó y posteriormente se documentó en el libro «Edinburgh LCF» de 1979, escrito por Milner junto con Gordon y Wadsworth. [ 5 ] [ 1 ]
Después de que Edinburgh LCF se estableció con la publicación del mismo nombre, el interés en el lenguaje creció y varias implementaciones, todas con ligeras alteraciones en el diseño y las características, fueron desarrolladas por varias partes. Luca Cardelli creó Cardelli ML , o VAX ML , que eventualmente se convirtió en un dialecto independiente apto para la computación de propósito general, especificado con el artículo ML under Unix . [ 7 ] [ 4 ] Gérard Huet en Inria comenzó a portar el código fuente de Stanford Lisp a varios otros dialectos de Lisp en "Project Formel". La adaptación a Franz Lisp fue desarrollada posteriormente por Larry Paulson , cuya versión finalmente se denominó Cambridge LCF . [ 8 ] Esta versión de LCF fue posteriormente actualizada para usar una versión temprana de Standard ML , y se ha subido a GitHub . [ 9 ]
Debido a la atención y el entusiasmo que suscitaban en aquel momento ML, LCF y otras tecnologías relacionadas, como el lenguaje de programación contemporáneo Hope , tras el lanzamiento de Edinburgh LCF y otros avances de la época, se convocó una reunión titulada "ML, LCF y Hope" en noviembre de 1982. En dicha reunión se plantearon las preocupaciones sobre la fragmentación tanto del diseño como de la implementación, que conllevaba la duplicación de esfuerzos. Si bien Milner se mostró receptivo al espíritu de experimentación, Bernard Sufrin y Milner mantuvieron más conversaciones y reuniones, en las que Sufrin instó a Milner a unificar el diseño de ML. Estas correspondencias se citaron posteriormente en el segundo borrador de la propuesta de Milner para Standard ML. [ 4 ]
Descripción general
La inspiración más notable de la sintaxis de ML se remonta a ISWIM , un lenguaje descrito como " cálculo lambda con azúcar sintáctico". [ 4 ] ML fue diseñado con un sistema de tipos estático robusto que permitía al usuario definir tipos abstractos con polimorfismo paramétrico y se verificaba en tiempo de compilación. [ 1 ] También contaba con inferencia automática de tipos, lo que le otorgaba a ML la facilidad de uso de lenguajes dinámicos de la época, como Lisp o POP-2, al prescindir de la necesidad de anotaciones de tipo explícitas. [ 4 ]
Ejemplos
Los siguientes ejemplos se derivan en gran medida del LCF de Edimburgo , y ofrecen una visión general de la sintaxis y las características de ML. El #carácter al inicio de una línea indica la entrada del usuario, y las líneas sin él son respuestas del sistema que muestran el valor y su tipo inferido. Cabe destacar que esta sección no pretende ser un conjunto exhaustivo de las características del lenguaje ML, sino un subconjunto para dar una idea general del mismo. Para una definición más rigurosa, consulte el LCF de Edimburgo . [ 1 ]
Las expresiones se evalúan escribiéndolas seguidas de ;;y un carácter de retorno. El identificador itcontiene el resultado de la última expresión evaluada. Las vinculaciones se introducen con let, y se pueden realizar múltiples vinculaciones simultáneamente uniéndolas con la andpalabra clave, o construyendo pares (que tiene un tipo de producto, explorado en un ejemplo posterior) en el lado derecho, que se compara con patrones a la izquierda:
5: int
- 2+3;;
x = 5 : int
- sea x = ello;;
y = 10 : int z = 7 : int
- sea y = 2*5 y z = 7;;
x = 10 : int y = 5 : int z = 2 : int
- sea x,y,z = y,x,2;;
Las funciones se definen con let. La aplicación de funciones tiene mayor precedencia que los operadores matemáticos, por lo que f 3 + 4significa (f 3) + 4. Las funciones definidas con múltiples parámetros se currifican , por lo que pasar un parámetro a la función devolverá una función que aceptará el segundo, y así sucesivamente. Las funciones recursivas requieren letrecpara que el nombre de la función esté dentro del ámbito de su cuerpo. La sintaxis para una función anónima es similar al cálculo lambda, con \para lambda y .separando los argumentos de la expresión:
sumar = - : (int -> (int -> int))
- sumemos xy = x+y;;
- : (int -> int)
- sumar 3;;
7: int
- es 4;;
hecho = - : (int -> int)
- letrec fact n = if n = 0 then 1 else n * fact(n-1);;
24: int
- hecho 4;;
4: int
- (\x.x+1) 3;;
Las listas usan punto y coma entre los elementos. hdy tlson funciones integradas que devuelven la cabeza y la cola; .es cons (anteponer); @es añadir. Las funciones como hdson polimórficas: ML usa variables de tipo genérico ( *, **, etc.) para expresar esto:
m = [1; 2; 3; 4] : (lista de enteros)
- sea m = [1;2;3;4];;
1, [2; 3; 4] : (int # (int lista))
- hd m, tl m;;
[0; 1; 2; 3; 4; 5; 6] : (lista de enteros)
- 0.m @ [5;6];;
- : ((* lista) -> *)
- HD;;
[1; 4; 9; 16] : (lista de enteros)
- mapa (\xx*x) [1;2;3;4];;
Las variables mutables se declaran con letrefy se actualizan con :=. La looppalabra clave pertenece a la estructura de bucle if-then, que se ejecuta cada vez que iffalla la condición:
hecho = - : (int -> int)
- sea hecho n =
- letref count = n y result = 1
- en si count = 0
- entonces resultado
- bucle count,result := count-1, count*result;;
24: int
- hecho 4;;
Los tokens son del tipo de cadena de ML, delimitados por `; las comillas invertidas dobles crean listas de tokens. Un uso común de los tokens era identificar fallos con failwith, una palabra clave utilizada para generar excepciones con un token explícito, y ?se utiliza para capturarlo:
`este es un token` : tok
- `este es un token`;;
[`esto`; `es`; `un`; `token`; `lista`] : (lista de tokens)
- ``esta es una lista de tokens``;;
mitad = - : (int -> int)
- sea la mitad de n =
- Si n = 0, entonces falla con `cero`.
- de lo contrario, sea m = n/2
- en si n = 2*m entonces m sino fallar con `odd`;;
2: int
- mitad 4;;
EVALUACIÓN FALLIDA impar
- mitad 3;;
0: int
- mitad 3 ? 0;;
Los tipos abstractos se declaran con abstype, que crea un nuevo tipo y define las funciones que trabajan con él, manteniendo oculta la estructura interna (el tipo concreto a partir del cual se construye). Los tipos abstractos recursivos se declaran con absrectype, que permite que el tipo se utilice en su propia definición. Existe una palabra clave similar lettype, , que se utiliza para alias de tipos más básicos . Aquí hay un tipo abstracto recursivo que define un árbol binario con algunas operaciones básicas:
tiptree = - : (* -> (*, **) árbol) comptree = - : ((** # (*, **) árbol # (*, **) árbol) -> (*, **) árbol) istip = - : ((*, **) árbol -> bool) tipof = - : ((*, **) árbol -> *) etiqueta de = - : ((*, **) árbol -> **) hijos de = - : ((*, **) árbol -> ((*, **) árbol # (*, **) árbol))
- absrectype (*, **) árbol = * + ** # (*, **) árbol # (*, **) árbol
- con tiptree x = abstree(inl x)
- y comptree (y, t1, t2) = abstree(inr(y, t1, t2))
- y istip t = isl(reptree t)
- y tipof t = outl(reptree t) ? failwith `tipof`
- y labelof t = fst(outr(reptree t)) ? failwith `labelof`
- y sonsof t = snd(outr(reptree t)) ? fallar con `sonsof`;;
Dentro de las definiciones de operación (el withbloque), el nombre del tipo puede ir precedido de abspara encapsular valores en el tipo y reppara desencapsular valores. Los caracteres +y #en las definiciones de tipo significan tipos suma (uniones etiquetadas) y tipos producto (tuplas), respectivamente, con #una precedencia mayor.
ML en LCF proporcionó varias funciones auxiliares utilizadas en el ejemplo anterior. Operando en tipos suma +, las funciones inly inrinyectan valores en el lado izquierdo o derecho de un tipo suma. outlextrae de inyecciones izquierdas (falla si se le da una inyección derecha), y outrextrae de inyecciones derechas (falla si se le da una inyección izquierda). Para tipos producto #, las funciones de extracción son fsty snd, que extraen el primer y segundo componente de un par. Los tipos producto se construyen utilizando el operador infijo coma. En el ejemplo de árbol anterior, comptreetoma un único parámetro que es un patrón de par (y, t1, t2), que desestructura el par en sus tres componentes.
Véase también
Referencias
- 1 2 3 4 5 6 Gordon, M.; Milner, R.; Wadsworth, CP (1979). Edinburgh LCF: A Mechanized Logic of Computation . Lecture Notes in Computer Science. Berlín, Heidelberg: Springer Berlin Heidelberg. doi : 10.1007/3-540-09724-4 . ISBN 978-3-540-09724-2.
- ↑ Tate, Bruce; Dees, Ian; Daoud, Frederic; Moffitt, Jack (18 de noviembre de 2014). Siete lenguajes más en siete semanas: lenguajes que están dando forma al futuro . Programadores pragmáticos ( ed. P1.0). Dallas: The Pragmatic Bookshelf. págs. 97, 101. ISBN 978-1-941222-15-7
Suelo decir que "Elm es un lenguaje de la familia ML" para referirme a la herencia común de todos estos lenguajes [Haskell, OCaml, SML, F#]
. - ↑ Lenguaje de programación para "fuerzas especiales" de desarrolladores , Red rusa de desarrollo de software: Equipo del proyecto Nemerle , consultado el 24 de enero de 2021.
- 1 2 3 4 5 6 MacQueen, David; Harper, Robert; Reppy, John (2020-06-14). "La historia de Standard ML" . Actas de la ACM sobre lenguajes de programación . 4 (HOPL): 1–100 . doi : 10.1145/3386336 . ISSN 2475-1421 .
- 1 2 Gordon, Michael JC (1996). "De LCF a HOL: una breve historia" . Recuperado el 11 de octubre de 2007 .
- ↑ Milner, Robin (diciembre de 1978). "Una teoría del polimorfismo de tipos en programación" . Journal of Computer and System Sciences . 17 (3): 348– 375. doi : 10.1016/0022-0000(78)90014-4 .
- ↑ Cardelli, Luca (1983). "ML under Unix" (PDF) . Archivado del original (PDF) el 12 de noviembre de 2025. Recuperado el 25 de enero de 2025 .
- ↑ Gordon, Michael JC (1988), Birtwistle, Graham; Subrahmanyam, PA (eds.), "HOL: Un sistema generador de pruebas para lógica de orden superior" , Especificación, verificación y síntesis de VLSI , vol. 35, Boston, MA: Springer US, pp. 73–128 , doi : 10.1007/978-1-4613-2007-4_3 , ISBN 978-1-4612-9197-8, recuperado el 3 de enero de 2026
{{citation}}: CS1 mantenimiento: parámetro de trabajo con ISBN ( enlace ) - ^ Kohlhase, Michael (11 de mayo de 2024), kohlhase/CambridgeLCF , consultado el 3 de enero de 2026
Lecturas adicionales
- Christoph Kreitz, Vincent Rahli, Introducción al ML clásico ( Archivado el 8 de julio de 2024 ), Universidad de Cornell, octubre de 2011. Notas de clase sobre un dialecto del ML cercano en espíritu al LCF/ML .
- Luca Cardelli, Documentos ( Archivado el 25 de enero de 2026 ), Universidad de Oxford. Enumera los documentos relacionados con el desarrollo de Cardelli ML/ML bajo VMS/ML en Unix.
- Lenguajes de programación académica
- Lenguajes funcionales
- Lenguajes de programación de alto nivel
- Familia de lenguajes de programación ML
- Lenguajes de programación que coinciden con patrones
- Lenguajes de programación creados en 1973
- Lenguajes de programación de tipado estático