🔵 F# — 2005

⬅️ Atlas · 🗂️ Todas las fichas · 📚 Índice de clases

F# es OCaml sobre .NET, y es la demostración de que un lenguaje funcional puede vivir en un ecosistema empresarial sin renunciar a nada: usa las mismas bibliotecas que C#, interopera sin fricción, y muchas de las mejores ideas de C# de la última década llegaron desde aquí.

🎯 Por qué está en este programa

F# es un primo de la familia .NET (Atlas), cuyo representante en el núcleo es C#, y también de la familia funcional tipada (ML).

Aporta al programa la inferencia de tipos completa al estilo Hindley-Milner —tipado estático sin escribir casi ningún tipo— y los tipos de datos algebraicos con emparejamiento exhaustivo (clase 100), que son las dos ideas de ML que hoy están llegando a todos los lenguajes.

Año 2005; 1.0 en 2010; hoy en F# 9, con .NET
Autoría Don Syme, Microsoft Research Cambridge — también autor de los genéricos de .NET
Familia .NET y funcional tipada (ML); descendiente directo de OCaml
Paradigma Funcional primero, con OO completo cuando hace falta
Tipado Estático con inferencia total; tipos algebraicos y unidades de medida
Memoria La del CLR: recolección de basura
Ejecución Bytecode IL sobre el CLR, con JIT o AOT nativo
Estado 🟢 Vivo y minoritario; muy usado en finanzas y análisis de datos

📜 Historia

Don Syme trabajaba en Microsoft Research y tiene un mérito que conviene conocer: diseñó e implementó los genéricos de .NET —reificados, a diferencia de los de Java (clase 108)— y lo hizo, en parte, porque los necesitaba para poder llevar ML a la plataforma.

Es una historia poco común: una característica del ecosistema entero existe porque alguien quería hacer un lenguaje funcional en él.

F# apareció en 2005 como puerto de OCaml sobre .NET, y se convirtió en producto oficial de Microsoft en 2010. Desde entonces es de código abierto y multiplataforma, con la F# Software Foundation implicada en su gobierno.

Y su influencia sobre su hermano mayor es grande y está documentada: los registros, el emparejamiento de patrones, los tipos con nulabilidad, async/await y las expresiones switch de C# vienen, en buena parte, de F#. Es el laboratorio de la plataforma.

🏭 Dónde vive hoy

🧠 Lo que enseña: inferencia total y tipos algebraicos

Uno, la inferencia Hindley-Milner:

let sumar a b = a + b            // ← ni un tipo escrito
// el compilador deduce: int -> int -> int

let procesar lista =
    lista |> List.filter (fun x -> x > 0) |> List.sum
// deduce: int list -> int

Tipado estático completo sin escribir tipos. Es más fuerte que la inferencia local de C# con var o de Java: F# infiere las firmas de las funciones, no solo las variables locales.

Dos, los tipos algebraicos con exhaustividad:

type Forma =
    | Circulo of radio: float
    | Rectangulo of ancho: float * alto: float

let area f =
    match f with
    | Circulo r -> System.Math.PI * r * r
    | Rectangulo (a, b) -> a * b
    // ← si falta un caso, el compilador AVISA

Y la combinación de las dos cosas es lo que hace productivo el estilo: se modela el dominio con tipos que hacen imposible representar un estado inválido, y el compilador comprueba que se han tratado todos los casos (clase 166).

Y tres, dos cosas que F# tiene y casi nadie más:

[<Measure>] type m
[<Measure>] type s
let velocidad = 100.0<m> / 9.58<s>    // float<m/s>
// let error = 100.0<m> + 9.58<s>       ← ✗ NO COMPILA

Las unidades de medida comprobadas en compilación, sin coste en ejecución. Es exactamente lo que la clase 166 señalaba con el Mars Climate Orbiter: el contrato de las unidades, en el tipo.

type Datos = CsvProvider<"ventas.csv">     // ← el TIPO se genera del fichero
let filas = Datos.Load("ventas.csv")
filas.Rows |> Seq.sumBy (fun r -> r.Importe)   // con autocompletado y comprobación

Los proveedores de tipos leen un esquema —CSV, JSON, SQL, un servicio web— en tiempo de compilación y generan los tipos. Es metaprogramación (clase 123) aplicada al problema de la clase 170: el desajuste de impedancia resuelto generando el tipo desde el esquema.

🔄 Lo que se ha modernizado

⚙️ Cómo se ejecuta hoy

dotnet fsi main.fsx < entrada.txt         # ejecutar como guion
dotnet run                                  # como proyecto

dotnet fsi                                  # consola interactiva
dotnet test                                  # pruebas, con Expecto o xUnit (clase 139)

🧪 El programa de la clase 041 en F#

let [| precio; cantidad; descuento |] =
    stdin.ReadLine().Split(' ') |> Array.map float
let total = precio * cantidad * (1.0 - descuento)
printfn "Total: %.2f" total

Lo que hay que ver.

📚 Fuentes y bibliografía


⏮️ Volver al Atlas · 🗂️ Todas las fichas · 🔗 Relacionadas: OCaml · C# · Haskell · Elm · Scala