stringtranslate.com

ML (lenguaje de programación)

ML ( Meta Language ) es un lenguaje de programación funcional de alto nivel y propósito general . Es conocido por su uso del sistema de tipos polimórfico Hindley-Milner , que asigna automáticamente los tipos de datos de la mayoría de las expresiones sin requerir anotaciones de tipo explícitas ( inferencia de tipo ), y garantiza la seguridad de los tipos; existe una prueba formal de que un programa ML bien tipificado no causa errores de tipo en tiempo de ejecución. [1] ML proporciona coincidencia de patrones para argumentos de función, recolección de basura , programación imperativa , llamada por valor y currying . Si bien es un lenguaje de programación de propósito general , ML se usa mucho en la investigación de lenguajes de programación y es uno de los pocos lenguajes que se especifica y verifica por completo utilizando semántica formal . Sus tipos y coincidencia de patrones lo hacen adecuado y de uso común para operar en otros lenguajes formales, como en la escritura de compiladores , la demostración automatizada de teoremas y la verificación formal .

Descripción general

Las características de ML incluyen una estrategia de evaluación de llamada por valor , funciones de primera clase , gestión automática de memoria a través de recolección de basura, polimorfismo paramétrico , tipado estático , inferencia de tipos , tipos de datos algebraicos , coincidencia de patrones y manejo de excepciones . ML utiliza reglas de alcance estático . [2]

Se puede decir que ML es un lenguaje funcional impuro , porque, aunque fomenta la programación funcional, permite efectos secundarios [3] (como lenguajes como Lisp , pero a diferencia de un lenguaje puramente funcional como Haskell ). Como la mayoría de los lenguajes de programación, ML utiliza evaluación diligente , lo que significa que siempre se evalúan todas las subexpresiones, aunque se puede lograr una evaluación diferida mediante el uso de cierres . Por lo tanto, se pueden crear y usar flujos infinitos como en Haskell, pero su expresión es indirecta.

Los puntos fuertes de ML se aplican principalmente en el diseño y manipulación del lenguaje (compiladores, analizadores, demostradores de teoremas), pero es un lenguaje de propósito general que también se utiliza en bioinformática y sistemas financieros.

ML fue desarrollado por Robin Milner y otros a principios de la década de 1970 en la Universidad de Edimburgo , [4] y su sintaxis está inspirada en ISWIM . Históricamente, ML fue concebido para desarrollar tácticas de prueba en el demostrador de teoremas LCF (cuyo lenguaje, pplambda , una combinación del cálculo de predicados de primer orden y el cálculo lambda polimórfico de tipos simples , tenía ML como su metalenguaje).

En la actualidad, existen varios lenguajes en la familia ML; los tres más destacados son Standard ML (SML), OCaml y F# . Las ideas de ML han influenciado a muchos otros lenguajes, como Haskell , Cyclone , Nemerle , [5] ATS y Elm . [6]

Ejemplos

Los siguientes ejemplos utilizan la sintaxis de ML estándar. Otros dialectos de ML, como OCaml y F#, presentan pequeñas diferencias.

Factorial

La función factorial expresada como ML pura:

 dato  curioso ( 0  :  int )  :  int  =  1  |  fac  ( n  :  int )  :  int  =  n  *  fac  ( n  -  1 )

Esto describe el factorial como una función recursiva, con un único caso base de terminación. Es similar a las descripciones de los factoriales que se encuentran en los libros de texto de matemáticas. Gran parte del código de ML es similar a las matemáticas en cuanto a facilidad y sintaxis.

Parte de la definición mostrada es opcional y describe los tipos de esta función. La notación E : t puede leerse como la expresión E tiene tipo t . Por ejemplo, al argumento n se le asigna el tipo entero (int), y fac (n : int), el resultado de aplicar fac al entero n, también tiene tipo entero. La función fac en su totalidad tiene entonces el tipo función de entero a entero (int -> int), es decir, fac acepta un entero como argumento y devuelve un resultado entero. Gracias a la inferencia de tipos, las anotaciones de tipo pueden omitirse y serán derivadas por el compilador. Reescrito sin las anotaciones de tipo, el ejemplo se ve así:

 dato  curioso 0  =  1  |  fac  n  =  n  *  fac  ( n  -  1 )

La función también se basa en la búsqueda de patrones, una parte importante de la programación ML. Tenga en cuenta que los parámetros de una función no están necesariamente entre paréntesis, sino separados por espacios. Cuando el argumento de la función es 0 (cero), devolverá el entero 1 (uno). Para todos los demás casos, se prueba la segunda línea. Esta es la recursión y ejecuta la función nuevamente hasta que se alcanza el caso base.

No se garantiza que esta implementación de la función factorial finalice, ya que un argumento negativo provoca una cadena infinita descendente de llamadas recursivas. Una implementación más robusta comprobaría si hay un argumento no negativo antes de realizar la recursión, de la siguiente manera:

 Dato  curioso n  =  let  fun  fac  0  =  1  |  fac  n  =  n  *  fac  ( n  -  1 )  in  if  ( n  <  0 )  then  raise  Domain  else  fac  n  end

El caso problemático (cuando n es negativo) demuestra un uso del sistema de excepciones de ML.

La función se puede mejorar aún más escribiendo su bucle interno como una llamada de cola , de modo que la pila de llamadas no necesite crecer en proporción al número de llamadas de función. Esto se logra agregando un parámetro adicional, acumulador , a la función interna. Por último, llegamos a

 Dato  curioso n  =  let  fun  fac  0  acc  =  acc  |  fac  n  acc  =  fac  ( n  -  1 )  ( n  *  acc )  in  if  ( n  <  0 )  then  raise  Domain  else  fac  n  1  end

Lista inversa

La siguiente función invierte los elementos de una lista. Más precisamente, devuelve una nueva lista cuyos elementos están en orden inverso en comparación con la lista dada.

diversión  inversa  []  =  []  |  inversa  ( x  ::  xs )  =  ( inversa  xs )  @  [ x ]

Esta implementación de la función inversa, aunque correcta y clara, es ineficiente y requiere un tiempo cuadrático para su ejecución. La función se puede reescribir para que se ejecute en tiempo lineal :

diversión  'a  reverse  xs  :  'a  lista  =  List . foldl  ( op  :: )  []  xs

Esta función es un ejemplo de polimorfismo paramétrico, es decir, puede consumir listas cuyos elementos tengan cualquier tipo y devolver listas del mismo tipo.

Módulos

Los módulos son el sistema de ML para estructurar grandes proyectos y bibliotecas. Un módulo consta de un archivo de firma y uno o más archivos de estructura. El archivo de firma especifica la API que se implementará (como un archivo de encabezado de C o un archivo de interfaz de Java ). La estructura implementa la firma (como un archivo de origen de C o un archivo de clase de Java). Por ejemplo, lo siguiente define una firma aritmética y una implementación de la misma utilizando números racionales:

firma  ARITH  = sig  tipo  t  val  cero  :  t  val  succ  :  t  ->  t  val  suma  :  t  *  t  ->  t fin
estructura  Racional  :  ARITH  = estructura  tipo de datos  t  =  Rat  de  int  *  int  val  cero  =  Rat  ( 0 ,  1 )  fun  succ  ( Rat  ( a ,  b ))  =  Rat  ( a  +  b ,  b )  fun  suma  ( Rat  ( a ,  b ),  Rat  ( c ,  d ))  =  Rat  ( a  *  d  +  c  *  b  ,  b  *  d ) fin

Estos se importan al intérprete mediante el comando 'use'. La interacción con la implementación solo se permite a través de las funciones de firma; por ejemplo, no es posible crear un objeto de datos 'Rat' directamente a través de este código. El bloque 'structure' oculta todos los detalles de la implementación al exterior.

Las bibliotecas estándar de ML se implementan como módulos de esta manera.

Véase también

Referencias

  1. ^ Robin Milner. Una teoría del polimorfismo de tipos en programación. Journal of Computer and System Sciences, 17(3):348–375, 1978.
  2. ^ Milner, Robin; Tofte, Mads (1991). "4.1 Contextos, entornos y alcance". Comentario sobre el aprendizaje automático estándar . The MIT Press. pp. 35–36. ISBN 0-262-63137-7.
  3. ^ Sebesta, Robert (1999). Conceptos de lenguajes de programación (4.ª ed.). Addison-Westley. pág. 54. ISBN 0-201-38596-1.
  4. ^ Gordon, Michael JC (1996). "De LCF a HOL: una breve historia" . Consultado el 11 de octubre de 2007 .
  5. ^ Lenguaje de programación para "fuerzas especiales" de desarrolladores, Red de desarrollo de software ruso: Equipo del proyecto Nemerle , consultado el 24 de enero de 2021
  6. ^ Tate, Bruce A.; Daoud, Fred; Dees, Ian; Moffitt, Jack (2014). "3. Elm". Siete idiomas más en siete semanas (versión del libro: P1.0-edición de noviembre de 2014). The Pragmatic Programmers, LLC. págs. 97, 101. ISBN 978-1-941222-15-7En la página 101 , el creador de Elm, Evan Czaplicki, dice: "Suelo decir "Elm es un lenguaje de la familia ML" para referirme a la herencia compartida de todos estos lenguajes". ["Estos lenguajes" se refiere a Haskell, OCaml, SML y F#.]

Lectura adicional

Enlaces externos