OCaml

OCaml
Desarrollador(es)
Inria
ocaml.org
Información general
Extensiones comunes .ml, .mli
Paradigma Multiparadigma, funcional, imperativa, modular, orientada a objetos
Apareció en 1996
Diseñado por Xavier Leroy, Jérôme Vouillon, Damien Doligez, Didier Rémy, Ascánder Suárez
Sistema de tipos Inferido, estático, fuerte, estructural.
Dialectos ML: Caml
Influido por C, Caml, Modula-3, Pascal, Standard ML
Ha influido a ATS, Coq, Elm, F Sharp, F*, Haxe, Opa, Rust, Scala
Sistema operativo Multiplataforma: Linux, Unix, macOS, Windows
Licencia LGPLv2.1

OCaml ( /ˈkæməl/, anteriormente Objective Caml) es un lenguaje de programación para propósitos generales, de alto nivel y multiparadigma que extiende el dialecto Caml de ML con características orientadas a objetos. OCaml fue creado en 1996 por Xavier Leroy, Jérôme Vouillon,[1]​ Damien Doligez, Didier Rémy,[2]​ Ascánder Suárez y otros.

La cadena de herramientas de OCaml incluye un intérprete interactivo de nivel superior, un compilador de código intermedio (bytecode), un compilador optimizado de código nativo, un depurador reversible y un gestor de paquetes (OPAM), junto con un sistema de construcción modular para OCaml (Dune). OCaml se desarrolló inicialmente en el contexto de la demostración automática de teoremas y se utiliza en software de análisis estático y métodos formales. Más allá de estas áreas, ha encontrado aplicaciones en la programación de sistemas, desarrollo web y utilidades financieras específicas, entre otros dominios.

El acrónimo CAML originalmente significaba «Lenguaje de Máquina Abstracta Categórica» (Categorical Abstract Machine Language), pero OCaml omite esta máquina abstracta.[3]​ OCaml es un proyecto de software libre y de código abierto gestionado y mantenido principalmente por el Instituto Nacional de Investigación en Informática y Automática de Francia (Inria). A principios de los años 2000, elementos de OCaml fueron adoptados por muchos lenguajes, especialmente F# y Scala.

Filosofía

Los lenguajes derivados de ML son más conocidos por sus sistemas de tipos estáticos y sus compiladores con inferencia de tipos. OCaml unifica la programación funcional, imperativa y orientada a objetos bajo un sistema de tipos similar al de ML. Por lo tanto, los programadores no necesitan estar profundamente familiarizados con el paradigma de lenguajes puramente funcionales para utilizar OCaml.

Al requerir que el programador trabaje dentro de las restricciones de su sistema de tipos estático, OCaml elimina muchos de los problemas relacionados con tipos runtime de ejecución asociados con lenguajes tipo dinámico. Además, el compilador con inferencia de tipos de OCaml reduce significativamente la necesidad de anotaciones de tipo manuales que son obligatorias en la mayoría de los lenguajes tipo estático. Por ejemplo, los tipos de datos de las variables y las signaturas de las funciones generalmente no necesitan declararse explícitamente, como ocurre en lenguajes como Java y C#, ya que pueden inferirse a partir de los operadores y otras funciones aplicadas a las variables y valores en el código. Aunque el uso efectivo del sistema de tipos de OCaml puede requerir cierta sofisticación por parte del programador, esta disciplina se recompensa con software confiable y de alto rendimiento.

OCaml se distingue de otros lenguajes con orígenes académicos principalmente por su énfasis en el rendimiento. Su sistema de tipos estático previene desajustes de tipo en tiempo de ejecución y, por lo tanto, elimina la necesidad de verificaciones de tipo y seguridad en tiempo de ejecución que afectan el rendimiento de los lenguajes de tipado dinámico, mientras garantiza la seguridad en tiempo de ejecución, excepto cuando se desactiva la verificación de límites de arreglos o se utilizan características inseguras, como la serialización. Estas excepciones son lo suficientemente raras como para evitarlas en la práctica.

Además de la sobrecarga de la comprobación de tipos, los lenguajes de programación funcional son, en general, difíciles de compilar a un código de máquina eficiente debido a problemas como el problema funarg. Junto con las optimizaciones estándar de bucles, registros e instrucciones, el compilador optimizador de OCaml emplea métodos de análisis estático del programa para optimizar la asignación de clausura y el empaquetamiento de valores, maximizando el rendimiento del código resultante incluso si utiliza ampliamente construcciones de programación funcional.

Xavier Leroy ha afirmado que «OCaml ofrece al menos el 50% del rendimiento de un compilador de C decente»,[4]​ aunque una comparación directa es imposible. Algunas funciones de la biblioteca estándar de OCaml están implementadas con algoritmos más rápidos que las funciones equivalentes en las bibliotecas estándar de otros lenguajes. Por ejemplo, la implementación de la unión de conjuntos en la biblioteca estándar de OCaml es teóricamente más eficiente que la función equivalente en las bibliotecas estándar de lenguajes imperativos (e.g., C++, Java), ya que la implementación de OCaml puede aprovechar la inmutabilidad de los conjuntos para reutilizar partes de los conjuntos de entrada en el conjunto de salida (véase estructura de datos persistente).

Historia

El equipo de desarrollo de OCaml recibiendo un premio en el Simposio sobre Principios de Lenguajes de Programación (POPL) 2024.

Desarrollo de ML (Meta Language)

Entre las décadas de 1970 y 1980, Robin Milner, un científico informático británico y ganador del Premio Turing, trabajó en el Laboratorio de Fundamentos de Ciencias de la Computación de la Universidad de Edimburgo.[5][6]​ Milner y otros estaban trabajando en demostradores de teoremas, que históricamente se desarrollaban en lenguajes como Lisp. Milner se encontraba repetidamente con el problema de que los demostradores de teoremas intentaban afirmar que una prueba era válida combinando elementos que no constituían pruebas. Como resultado, desarrolló un metalinguaje para su Logic for Computable Functions (LCF), un lenguaje que solo permitía al usuario construir pruebas válidas gracias a su sistema de tipos polimórfico.[7]​ ML se convirtió en un compilador para simplificar el uso de LCF en diferentes máquinas y, para la década de 1980, se había convertido en un sistema completo por sí mismo.[7]​ ML eventualmente serviría como base para la creación de OCaml.

A principios de la década de 1980, surgieron algunos avances que llevaron al equipo Formel de INRIA a interesarse por el lenguaje ML. Luca Cardelli, profesor investigador de la Universidad de Oxford, utilizó su máquina abstracta funcional para desarrollar una implementación más rápida de ML, y Robin Milner propuso una nueva definición de ML para evitar divergencias entre las diversas implementaciones. Simultáneamente, Pierre-Louis Curien, un investigador principal de la Universidad de París Diderot, desarrolló un cálculo de combinadores categóricos y lo vinculó al cálculo lambda, lo que condujo a la definición de la máquina abstracta categórica (Categorical Abstract Machine, CAM). Guy Cousineau, investigador de la misma universidad, reconoció que esto podía aplicarse como método de compilación para ML.[3]

Primera implementación

Caml fue diseñado y desarrollado inicialmente por el equipo Formel de INRIA, dirigido por Gérard Huet. La primera implementación de Caml se creó en 1987 y se desarrolló aún más hasta 1992. Aunque el proyecto fue liderado inicialmente por Ascánder Suárez, Pierre Weis y Michel Mauny continuaron con el desarrollo después de que Suárez se retirara en 1988.[3]

Guy Cousineau recuerda que su experiencia con la implementación de lenguajes de programación era inicialmente muy limitada y que había múltiples deficiencias que atribuye a su responsabilidad. A pesar de ello, considera que "Ascander, Pierre y Michel hicieron un trabajo realmente destacado".[3]

Caml Light

Entre 1990 y 1991, Xavier Leroy diseñó una nueva implementación de Caml basada en un intérprete de código intermedio (bytecode) escrito en C. Además, Damien Doligez desarrolló un sistema de gestión de memoria, también conocido como recolector de basura secuencial, para esta implementación.[7]​ Esta nueva versión, conocida como Caml Light, reemplazó a la antigua implementación de Caml y estaba diseñada para funcionar en pequeñas computadoras de escritorio.[3]​ En los años siguientes, aparecieron bibliotecas como las herramientas de manipulación de sintaxis creadas por Michel Mauny, las cuales ayudaron a promover el uso de Caml en equipos educativos y de investigación.[7]

Caml Special Light

En 1995, Xavier Leroy lanzó Caml Special Light, una versión mejorada de Caml.[3]​ Se añadió un compilador optimizador de código nativo al compilador de código intermedio, lo que incrementó significativamente el rendimiento, alcanzando niveles comparables a lenguajes populares como C++.[7][3]​ Además, Leroy diseñó un sistema de módulos de alto nivel inspirado en el sistema de módulos de Standard ML, que ofrecía potentes herramientas para la abstracción y la parametrización, facilitando el desarrollo de programas a mayor escala.[7]

Objective Caml

Didier Rémy y Jérôme Vouillon diseñaron un sistema de tipos expresivo para objetos y clases, que fue integrado en Caml Special Light. Esto dio lugar al lenguaje Objective Caml, lanzado por primera vez en 1996 y renombrado como OCaml en 2011. Este sistema de objetos soportaba muchos de los paradigmas de programación orientada a objetos de manera segura con tipos estáticos, mientras que esos mismos paradigmas causaban inconsistencias o requerían verificaciones en tiempo de ejecución en lenguajes como C++ o Java. En el año 2000, Jacques Garrigue extendió Objective Caml con múltiples características nuevas, como métodos polimórficos, variantes y argumentos etiquetados y opcionales.[7][3]

Desarrollo continuo

Durante las últimas dos décadas, se han añadido mejoras incrementales al lenguaje para soportar las crecientes bases de código comerciales y académicas en OCaml.[7]​ La versión 4.0 de OCaml, lanzada en 2012, incorporó Tipos de Datos Algebraicos Generalizados (GADTs) y módulos de primera clase, aumentando la flexibilidad del lenguaje.[7]​ La versión 5.0.0 de OCaml, lanzada en 2022,[8]​ representó una reescritura completa del entorno de ejecución del lenguaje, eliminando el bloqueo global del recolector de basura (GC lock) y añadiendo controladores de efectos mediante continuaciones delimitadas. Estos cambios habilitaron el soporte para paralelismo en memoria compartida y concurrencia transparente, respectivamente.

El desarrollo de OCaml continuó en el equipo Cristal de INRIA hasta 2005, cuando fue sucedido por el equipo Gallium.[9]​ Posteriormente, en 2019, Gallium fue reemplazado por el equipo Cambium.[10][11]​ A partir de 2023, el compilador de OCaml cuenta con 23 desarrolladores principales de diversas organizaciones,[12]​ mientras que el ecosistema más amplio de herramientas y paquetes de OCaml incluye a 41 desarrolladores.[13]​ En 2023, el compilador de OCaml fue reconocido con el Premio al Software de Lenguajes de Programación de ACM SIGPLAN.

Características

OCaml cuenta con un sistema de tipos estáticos, inferencia de tipos, polimorfismo paramétrico, recursión de cola, coincidencia de patrones, clausuras léxicas de primera clase, funtores (módulos paramétricos), manejo de excepciones, manejo de efectos y recolección automática de basura incremental generacional.

Una de las características más destacadas de OCaml es su extensión de la inferencia de tipos al sistema de objetos en un lenguaje de propósito general. Esto permite subtipado estructural, donde los tipos de objeto son compatibles si sus firmas de métodos son compatibles, independientemente de su herencia declarada, una característica poco común en lenguajes con tipado estático.

OCaml incluye una interfaz de funciones foráneas para enlazar con primitivas en C, incluyendo soporte para vectores numéricos eficientes en formatos compatibles tanto con C como con Fortran. Además, OCaml permite crear bibliotecas de funciones en OCaml que pueden enlazarse con programas principales escritos en C, lo que facilita su distribución a programadores en C sin necesidad de que estos tengan conocimientos o instalaciones de OCaml.

Aunque OCaml no cuenta con un sistema de macros como parte indivisible del lenguaje (metaprogramación) con soporte integrado para preprocesamiento, la plataforma OCaml ofrece oficialmente una biblioteca para escribir estos preprocesadores. Existen dos tipos: uno que trabaja a nivel de código fuente (como en C) y otro que opera a nivel del árbol de sintaxis abstracta (Abstract Syntax Tree). Este último, conocido como PPX (Pre-Processor eXtension), es el recomendado.

La distribución de OCaml incluye:

El compilador de código nativo está disponible para varias plataformas, incluyendo Unix, Microsoft Windows y Apple macOS. La portabilidad se logra gracias al soporte de generación de código nativo para arquitecturas importantes como:

  • X86-64 (AMD64), RISC-V y ARM64 (en OCaml 5.0.0 y versiones superiores).[14]
  • IBM Z (antes de OCaml 5.0.0 y nuevamente en OCaml 5.1.0).
  • Power (antes de OCaml 5.0.0 y programado para reaparecer en OCaml 5.2.0).
  • IA-32 y ARM (antes de OCaml 5.0.0).
  • SPARC (antes de OCaml 4.06.0).
  • DEC Alpha, HPPA, IA64 y MIPS (antes de OCaml 4.00.0).

El compilador de código intermedio (bytecode) funciona en cualquier arquitectura de 32 o 64 bits cuando no está disponible la generación de código nativo, requiriendo únicamente un compilador en C.

Los programas en OCaml, tanto de código intermedio como de código nativo, pueden escribirse en un estilo multihilo con cambio de contexto preventivo. Los hilos de OCaml en el mismo dominio[15]​ se ejecutan solo mediante compartición de tiempo. Sin embargo, un programa en OCaml puede contener múltiples dominios.

Ejemplos de código

Los fragmentos de código en OCaml se estudian mejor introduciéndolos en el REPL (Read-Eval-Print Loop), una sesión interactiva de OCaml que muestra los tipos inferidos y los resultados de las expresiones definidas.[16]​ El entorno interactivo se inicia ejecutando simplemente el programa OCaml:

$ ocaml
     Objective Caml version 3.09.0
#

El código se puede ingresar en el indicador #. Por ejemplo, para calcular 1 + 2 * 3:

# 1 + 2 * 3;;
- : int = 7

OCaml infiere que el tipo de la expresión es int (un entero de precisión de máquina) y da como resultado 7.

Hello World

El siguiente programa llamado hello.ml:

print_endline "Hello World!"

Se puede compilar a un ejecutable en código intermedio (bytecode):

$ ocamlc hello.ml -o hello

O compilarlo a un ejecutable optimizado en código nativo:

$ ocamlopt hello.ml -o hello

Y ejecutarlo:

$ ./hello
Hello World!
$

El primer argumento para ocamlc, "hello.ml", especifica el archivo fuente a compilar, mientras que el indicador "-o hello" especifica el archivo de salida.[17]

Option

El constructor de tipo option en OCaml, similar al tipo Maybe en Haskell, extiende un tipo de datos dado para devolver Some (un valor del tipo especificado) o None. Esto expresa que un valor puede o no estar presente.

# Some 42;;
- : int option = Some 42
# None;;
- : 'a option = None

Este es un ejemplo de una función que extrae un int de una opción (option). Si contiene un valor, lo convierte en una cadena de caracteres; si no, retorna una cadena vacía:

let extract o =
  match o with
  | Some i -> string_of_int i
  | None -> "";;
# extract (Some 42);;
- : string = "42"
# extract None;;
- : string = ""

Sumando una lista de enteros

Las listas son uno de los tipos de datos fundamentales en OCaml. El siguiente ejemplo de código define una función recursiva llamada sum que acepta un argumento, integers, que debe ser una lista de enteros. Observa la palabra clave rec, que indica que la función es recursiva. La función itera recursivamente sobre la lista de enteros proporcionada y calcula la suma de sus elementos. La instrucción match tiene ciertas similitudes con el elemento switch de C, aunque es mucho más general.

let rec sum integers =                   (* Keyword rec means 'recursive'. *)
  match integers with
  | [] -> 0                              (* Yield 0 if integers is the empty 
                                            list []. *)
  | first :: rest -> first + sum rest;;  (* Recursive call if integers is a non-
                                            empty list; first is the first 
                                            element of the list, and rest is a 
                                            list of the rest of the elements, 
                                            possibly []. *)
  # sum [1;2;3;4;5];;
  - : int = 15

Otra forma es usar la función estándar fold, que trabaja con listas.

let sum integers =
  List.fold_left (fun accumulator x -> accumulator + x) 0 integers;;
  # sum [1;2;3;4;5];;
  - : int = 15

Dado que la función anónima es simplemente la aplicación del operador +, esto se puede simplificar a:

let sum integers =
  List.fold_left (+) 0 integers

Además, se puede omitir el argumento de la lista utilizando una aplicación parcial:

let sum =
  List.fold_left (+) 0

Quicksort

OCaml puede expresar de manera concisa algoritmos recursivos. El siguiente ejemplo de código implementa un algoritmo similar al quicksort, que ordena una lista en orden ascendente.

 let rec qsort = function
   | [] -> []
   | pivot :: rest ->
     let is_less x = x < pivot in
     let left, right = List.partition is_less rest in
     qsort left @ [pivot] @ qsort right

O usando la aplicación parcial del operador >=.

 let rec qsort = function
   | [] -> []
   | pivot :: rest ->
     let is_less = (>=) pivot in
     let left, right = List.partition is_less rest in
     qsort left @ [pivot] @ qsort right

Paradoja del cumpleaños

El siguiente programa calcula el número mínimo de personas en una sala para que la probabilidad de que todas tengan cumpleaños únicos sea menor al 50% (el problema del cumpleaños). Para 1 persona, la probabilidad es 365/365 (100%); para 2, es 364/365; para 3, es 364/365 × 363/365, y así sucesivamente. La respuesta es 23.

let year_size = 365.

let rec birthday_paradox prob people =
  let prob = (year_size -. float people) /. year_size *. prob  in
  if prob < 0.5 then
    Printf.printf "answer = %d\n" (people+1)
  else
    birthday_paradox prob (people+1)
;;

birthday_paradox 1.0 1

Codificación de Church

El siguiente código define una codificación de Church de números naturales, junto con las operaciones de sucesor (succ) y suma (add). Un número de Church n es una función de orden superior que acepta una función f y un valor x, y aplica f a x exactamente x veces. Para convertir un número de Church en una representación de cadena, se le pasa una función que agrega el prefijo "S" a su entrada y la cadena constante "0".

let zero f x = x
let succ n f x = f (n f x)
let one = succ zero
let two = succ (succ zero)
let add n1 n2 f x = n1 f (n2 f x)
let to_string n = n (fun k -> "S" ^ k) "0"
let _ = to_string (add (succ two) two)

Función factorial de precisión arbitraria (biblioteca)

OCaml ofrece acceso directo a una variedad de bibliotecas, incluidas aquellas para realizar cálculos de precisión arbitraria. Dado que la función factorial crece rápidamente y supera rápidamente los límites de precisión de los números de máquina (normalmente de 32 o 64 bits), es un buen ejemplo para ilustrar el uso de aritmética de precisión arbitraria.

En OCaml, el módulo Num (ahora reemplazado por el módulo ZArith) proporciona soporte para cálculos de precisión arbitraria. Este módulo puede cargarse en un top-level interactivo con el siguiente comando:

# #use "topfind";;
# #require "num";;
# open Num;;

La función factorial se puede escribir utilizando los operadores numéricos de precisión arbitraria  =/,  */ y  -/:

# let rec fact n =
    if n =/ Int 0 then Int 1 else n */ fact(n -/ Int 1);;
val fact : Num.num -> Num.num = <fun>

Esta función puede calcular factoriales mucho más grandes, como 120!:

# string_of_num (fact (Int 120));;
- : string =
"6689502913449127057588118054090372586752746333138029810295671352301633
55724496298936687416527198498130815763789321409055253440858940812185989
8481114389650005964960521256960000000000000000000000000000"

Triángulo (gráficos)

El siguiente programa renderiza un triángulo rotatorio en 2D utilizando OpenGL:

let () =
  ignore (Glut.init Sys.argv);
  Glut.initDisplayMode ~double_buffer:true ();
  ignore (Glut.createWindow ~title:"OpenGL Demo");
  let angle t = 10. *. t *. t in
  let render () =
    GlClear.clear [ `color ];
    GlMat.load_identity ();
    GlMat.rotate ~angle: (angle (Sys.time ())) ~z:1. ();
    GlDraw.begins `triangles;
    List.iter GlDraw.vertex2 [-1., -1.; 0., 1.; 1., -1.];
    GlDraw.ends ();
    Glut.swapBuffers () in
  GlMat.mode `modelview;
  Glut.displayFunc ~cb:render;
  Glut.idleFunc ~cb:(Some Glut.postRedisplay);
  Glut.mainLoop ()

Se requieren los enlaces de LablGL para OpenGL. El programa puede ser compilado a bytecode con:

$ ocamlc -I +lablGL lablglut.cma lablgl.cma simple.ml -o simple

O con el código nativo:

$ ocamlopt -I +lablGL lablglut.cmxa lablgl.cmxa simple.ml -o simple

O, simplemente, utilizar el comando de construcción de ocamlfind:

$ ocamlfind opt simple.ml -package lablgl.glut -linkpkg -o simple

Y ejecutar:

$ ./simple

Se pueden desarrollar programas gráficos 2D y 3D mucho más sofisticados y de alto rendimiento en OCaml. Gracias al uso de OpenGL y OCaml, los programas resultantes pueden ser multiplataforma, compilando sin ningún cambio en muchas plataformas principales.

Sucesión de Fibonacci

El siguiente código calcula la sucesión de Fibonacci de un número n ingresado. Utiliza recursión de cola y coincidencia de patrones.

let fib n =
  let rec fib_aux m a b =
    match m with
    | 0 -> a
    | _ -> fib_aux (m - 1) b (a + b)
  in fib_aux n 0 1

Funciones de orden superior

Las funciones pueden recibir funciones como entrada y devolver funciones como resultado. Por ejemplo, aplicar la función twice a una función f genera una función que aplica f dos veces a su argumento.

let twice (f : 'a -> 'a) = fun (x : 'a) -> f (f x);;
let inc (x : int) : int = x + 1;;
let add2 = twice inc;;
let inc_str (x : string) : string = x ^ " " ^ x;;
let add_str = twice(inc_str);;
  # add2 98;;
  - : int = 100
  # add_str "Test";;
  - : string = "Test Test Test Test"

La función twice utiliza una variable de tipo 'a para indicar que puede aplicarse a cualquier función f que mapee de un tipo 'a a sí mismo, en lugar de estar restringida solo a funciones de tipo int -> int. En particular, twice incluso puede aplicarse a sí misma.

  # let fourtimes f = (twice twice) f;;
  val fourtimes : ('a -> 'a) -> 'a -> 'a = <fun>
  # let add4 = fourtimes inc;;
  val add4 : int -> int = <fun>
  # add4 98;;
  - : int = 102

Lenguajes derivados

MetaOCaml

MetaOCaml[18]​ es una extensión de programación de múltiples etapas de OCaml que permite la compilación incremental de nuevo código máquina durante el tiempo de ejecución. Bajo ciertas circunstancias, es posible obtener aumentos significativos de velocidad utilizando programación de múltiples etapas, porque se dispone de información más detallada sobre los datos a procesar en tiempo de ejecución que en el tiempo de compilación regular, por lo que el compilador incremental puede optimizar muchos casos de comprobación de condiciones, etc.

Como ejemplo: si en tiempo de compilación se sabe que una función de potencia x -> x^nse necesitará con frecuencia, pero el valor de n solo se conoce en tiempo de ejecución, se puede utilizar una función de potencia de dos etapas en MetaOCaml.

let rec power n x =
  if n = 0
  then .<1>.
  else
    if even n
    then sqr (power (n/2) x)
    else .<.~x *. .~(power (n - 1) x)>.

Tan pronto como se conozca n en tiempo de ejecución, se puede crear una función de potencia especializada y muy rápida.

.<fun x -> .~(power 5 .<x>.)>.

El resultado es:

fun x_1 -> (x_1 *
    let y_3 = 
        let y_2 = (x_1 * 1)
        in (y_2 * y_2)
    in (y_3 * y_3))

La nueva función se compila automáticamente.

Otros lenguajes derivados

  • F# es un lenguaje del marco .NET basado en OCaml.
  • JoCaml integra construcciones para desarrollar programas concurrentes y distribuidos.
  • Reason es una sintaxis y una cadena de herramientas alternativa para OCaml creada en Facebook, que puede compilar tanto a código nativo como a JavaScript.

Software escrito en OCaml

Usuarios

Al menos varias docenas de empresas usan OCaml en algún grado.[24]​ Ejemplos notables incluyen:

En el contexto de la enseñanza e investigación académica, OCaml tiene una presencia destacada en los programas de enseñanza de ciencias de la computación, tanto en universidades como en colegios. Una lista de recursos educativos y estos programas de enseñanza se pueden encontrar en ocaml.org.

Referencias

  1. «Jérôme Vouillon». www.irif.fr (en inglés). Consultado el 13 de diciembre de 2024. 
  2. «Didier Remy». pauillac.inria.fr (en inglés). Consultado el 13 de diciembre de 2024. 
  3. a b c d e f g h «A History of OCaml». OCaml (en inglés). Consultado el 13 de diciembre de 2024. 
  4. «Linux Weekly News». lwn.net (en inglés). Consultado el 13 de diciembre de 2024. 
  5. «A J Milner - A.M. Turing Award Laureate». amturing.acm.org (en inglés). Consultado el 13 de diciembre de 2024. 
  6. Michael Clarkson et al. «1.2. OCaml · Functional Programming in OCaml». courses.cs.cornell.edu (en inglés). Consultado el 13 de diciembre de 2024. 
  7. a b c d e f g h i «Prologue - Real World OCaml». dev.realworldocaml.org (en inglés). Consultado el 13 de diciembre de 2024. 
  8. «Release of OCaml 5.0.0 OCaml Package». OCaml (en inglés). 
  9. «Projet Cristal». cristal.inria.fr (en inglés). Consultado el 13 de diciembre de 2024. 
  10. «Gallium team - Home». gallium.inria.fr (en inglés). Consultado el 13 de diciembre de 2024. 
  11. «Home». cambium.inria.fr (en inglés). Consultado el 13 de diciembre de 2024. 
  12. «Compiler · OCaml Governance». OCaml (en inglés). Consultado el 13 de diciembre de 2024. 
  13. «Governance and projects». OCaml (en inglés). Consultado el 13 de diciembre de 2024. 
  14. «ocaml/asmcomp at trunk · ocaml/ocaml». GitHub (en inglés). Consultado el 13 de diciembre de 2024. 
  15. Un dominio es una unidad de paralelismo en OCaml; generalmente, un dominio corresponde a un núcleo de CPU.
  16. «OCaml - The toplevel system or REPL (ocaml)». ocaml.org. Consultado el 13 de diciembre de 2024. 
  17. «OCaml - Batch compilation (ocamlc)». ocaml.org (en inglés). Consultado el 14 de diciembre de 2024. 
  18. oleg-at-okmij.org. «BER MetaOCaml». okmij.org. Consultado el 14 de diciembre de 2024. 
  19. EasyCrypt/easycrypt (en inglés), EasyCrypt, 13 de diciembre de 2024, consultado el 14 de diciembre de 2024 .
  20. «Messenger.com Now 50% Converted to Reason · Reason». reasonml.github.io (en inglés). Consultado el 14 de diciembre de 2024. 
  21. «Flow: A Static Type Checker for JavaScript». Flow (en inglés). Archivado desde el original el 8 de abril de 2022. Consultado el 14 de diciembre de 2024. 
  22. «Infer Static Analyzer | Infer | Infer». Infer (en inglés). Consultado el 14 de diciembre de 2024. 
  23. WebAssembly/spec (en inglés), World Wide Web Consortium, 13 de diciembre de 2024, consultado el 14 de diciembre de 2024 .
  24. «OCaml in Industry». OCaml (en inglés). Consultado el 14 de diciembre de 2024. 
  25. «BuckleScript: The 1.0 release has arrived! | Bloomberg LP». Bloomberg L.P. (en inglés estadounidense). 8 de septiembre de 2016. Consultado el 14 de diciembre de 2024. 
  26. Scott, David; Sharp, Richard; Gazagnaire, Thomas; Madhavapeddy, Anil (27 de septiembre de 2010). «Using functional programming within an industrial product group: perspectives and perceptions». Proceedings of the 15th ACM SIGPLAN international conference on Functional programming. ICFP '10 (en inglés) (Association for Computing Machinery): 87-92. ISBN 978-1-60558-794-3. doi:10.1145/1863543.1863557. Consultado el 14 de diciembre de 2024. 
  27. Flow on GitHub (en inglés), GitHub, 2023, consultado el 14 de diciembre de 2024 .
  28. «OCaml For the Masses – Communications of the ACM» (en inglés estadounidense). 1 de noviembre de 2011. Consultado el 14 de diciembre de 2024. 
  29. Yaron Minsky (2016). «Keynote - Observations of a Functional Programmer» (en inglés). ACM Commercial Uses of Functional Programming. 
  30. Yaron Minsky (2023). «Signals and Threads». signalsandthreads.com (en inglés). Jane Street Capital. Consultado el 14 de diciembre de 2024. 
  31. Anil Madhavapeddy (18 de mayo de 2016). «Improving Docker with Unikernels: Introducing HyperKit, VPNKit and DataKit | Docker». www.docker.com (en inglés estadounidense). Docker, Inc. Consultado el 14 de diciembre de 2024. 
  32. «VPNKit on GitHub» (en inglés). GitHub. 2023. 

Enlaces externos