F Sharp (lenguaje de programación)
F# (pronunciado F sostenido) es un lenguaje de programación funcional primero, de propósito general, fuertemente tipado y multiparadigma que abarca funcionalidad, imperativo y objeto- métodos de programación orientados. Se utiliza con mayor frecuencia como un lenguaje de infraestructura de lenguaje común (CLI) multiplataforma en.NET, pero también puede generar código de unidad de procesamiento de gráficos (GPU) y JavaScript.
F# está desarrollado por F# Software Foundation, Microsoft y colaboradores abiertos. Un compilador multiplataforma de código abierto para F# está disponible en F# Software Foundation. F# es un lenguaje totalmente compatible con Visual Studio y JetBrains Rider. Existen complementos compatibles con F# para muchos editores ampliamente utilizados, incluidos Visual Studio Code, Vim y Emacs.
F# es miembro de la familia de lenguajes ML y se originó como una implementación de.NET Framework de un núcleo del lenguaje de programación OCaml. También ha sido influenciado por C#, Python, Haskell, Scala y Erlang.
Historia
Versiones
Versión | Especificación del idioma | Fecha | Plataformas | Hora de correr |
---|---|---|---|---|
F# 1.x | Mayo de 2005 | Windows | .NET 1.0 - 3.5 | |
F# 2.0 | Agosto de 2010 | Abril de 2010 | Linux, macOS, Windows | .NET 2.0 - 4.0, Mono |
F# 3.0 | Noviembre de 2012 | Agosto de 2012 | Linux, macOS, Windows; JavaScript, GPU | .NET 2.0 - 4.5, Mono |
F# 3.1 | Noviembre de 2013 | Octubre de 2013 | Linux, macOS, Windows; JavaScript, GPU | .NET 2.0 - 4.5, Mono |
F# 4.0 | Enero 2016 | Julio de 2015 | ||
F# 4.1 | Mayo 2018 | Marzo de 2017 | Linux, macOS, Windows,
JavaScript, GPU | .NET 3.5 - 4.6.2,.NET Core, Mono |
F# 4.5 | Agosto 2018 | Linux, macOS, Windows,
JavaScript, GPU | .NET 4.5 - 4.7.2,.NET Core SDK 2.1.400 | |
F# 4.6 | Marzo 2019 | Linux, macOS, Windows,
JavaScript, GPU | .NET 4.5 - 4.7.2,.NET Core SDK 2.2.300 | |
F# 4.7 | Septiembre 2019 | Linux, macOS, Windows,
JavaScript, GPU | .NET 4.5 - 4.8,.NET Core SDK 3.0.100 | |
F# 5.0 | Noviembre 2020 | Linux, macOS, Windows,
JavaScript, GPU | . NET SDK 5.0.100 | |
F# 6.0 | Noviembre 2021 | Linux, macOS, Windows,
JavaScript, GPU | . NET SDK 6.0.100 | |
F# 7.0 | Noviembre 2022 | Linux, macOS, Windows,
JavaScript, GPU | . NET SDK 7.0.100 |
Evolución del lenguaje
F# utiliza un proceso de ingeniería y desarrollo abierto. El proceso de evolución del lenguaje lo administra Don Syme de Microsoft Research como dictador benévolo de por vida (BDFL) para el diseño del lenguaje, junto con F# Software Foundation. Las versiones anteriores del lenguaje F# fueron diseñadas por Microsoft y Microsoft Research mediante un proceso de desarrollo cerrado.
F# se incluyó por primera vez en Visual Studio en la edición de 2010, al mismo nivel que Visual Basic y C# (aunque como opción), y se ha mantenido en ediciones posteriores, lo que hace que el lenguaje esté ampliamente disponible y sea compatible.
F# se origina en Microsoft Research, Cambridge, Reino Unido. El lenguaje fue originalmente diseñado e implementado por Don Syme, según quien en el equipo de fsharp, dicen que la F es para "Diversión". Andrew Kennedy contribuyó al diseño de unidades de medida. Las herramientas de Visual F# para Visual Studio están desarrolladas por Microsoft. F# Software Foundation desarrolló el compilador y las herramientas de código abierto de F#, incorporando la implementación del compilador de código abierto proporcionada por el equipo de Microsoft Visual F# Tools.
Características añadidas | |
---|---|
F# 1.0 |
|
F# 2.0 |
|
F# 3.0 |
|
F# 3.1 |
|
F# 4.0 |
|
F# 4.1 |
|
F# 4.5 |
|
F# 4.6 |
|
F# 4.7 |
|
F# 5.0 |
|
F# 6.0 |
|
F# 7.0 |
|
Descripción general del idioma
Programación funcional
Si bien es compatible con las características orientadas a objetos disponibles en C#, F# es un primer lenguaje funcional fuertemente tipado con una gran cantidad de capacidades que normalmente solo se encuentran en los lenguajes de programación funcionales. Juntas, estas características permiten que los programas de F# se escriban en un estilo completamente funcional y también permiten que se mezclen estilos funcionales y orientados a objetos.
Ejemplos de características funcionales son:
- Todo es una expresión
- Tipo de inferencia (usando Hindley-Milner tipo inferencia)
- Funciones como ciudadanos de primera clase
- Funciones anónimas con captura de semántica (es decir, cierres)
- Variables y objetos inmutables
- Apoyo a la evaluación lento
- Funciones superiores
- Funciones anidas
- Currying
- Pattern matching
- Tipos de datos algebraicos
- Tuples
- Comprensión de listas
- Soporte de patrón Monad (llamado expresiones de computación)
- Optimización de llamadas de cola
F# es un lenguaje basado en expresiones que utiliza una evaluación entusiasta y también, en algunos casos, una evaluación perezosa. Cada instrucción en F#,
incluidas las expresiones if
, las expresiones try
y los bucles, es una expresión componible con un tipo estático. Las funciones y expresiones que no devuelven ningún valor tienen un tipo de retorno de unit
. F# usa la palabra clave let
para vincular valores a un nombre. Por ejemplo:
Deja x = 3 + 4
vincula el valor 7
al nombre x
.
Los nuevos tipos se definen utilizando la palabra clave type
. Para la programación funcional, F# proporciona tupla, registro, unión discriminada, lista, opción y resultado tipos. Una tupla representa un conjunto de valores n, donde n ≥ 0. El valor n se denomina aridad de la tupla. Una tupla de 3 se representaría como (A, B, C)
, donde A, B y C son valores de tipos posiblemente diferentes. Una tupla se puede usar para almacenar valores solo cuando el número de valores se conoce en tiempo de diseño y se mantiene constante durante la ejecución.
Un registro es un tipo donde se nombran los miembros de datos. Aquí hay un ejemplo de definición de registro:
Tipo R = {} Nombre : cuerda Edad : int }
Los registros se pueden crear como let r = { Nombre="AB"; Edad=42
}. La palabra clave with
se usa para crear una copia de un registro, como en { r con Nombre="CD"
}, que crea un nuevo registro copiando r
y cambiando el valor del campo Name
(suponiendo que el registro creado en el último ejemplo se llamara r
).
Un tipo de unión discriminada es una versión de tipo seguro de las uniones C. Por ejemplo,
Tipo A = Silencio UnionCaseX de cuerda Silencio UnionCaseY de int
Los valores del tipo de unión pueden corresponder a cualquier caso de unión. Los tipos de valores transportados por cada caso de unión se incluyen en la definición de cada caso.
El tipo list es una lista enlazada inmutable representada mediante un cabeza::cola notación (
::
es el operador contras) o una abreviatura como [elemento1; elemento2; elemento3]
. Una lista vacía se escribe []
. El tipo opción es un tipo de unión discriminado con opciones Algunos(x)
o Ninguno
. Los tipos de F# pueden ser genéricos, implementados como tipos genéricos.NET.
F# admite cierres y funciones lambda. Todas las funciones en F# son valores de primera clase y son inmutables. Las funciones se pueden curry. Al ser valores de primera clase, las funciones se pueden pasar como argumentos a otras funciones. Al igual que otros lenguajes de programación funcional, F# permite la composición de funciones mediante los operadores >>
y <<
.
F# proporciona expresiones de secuencia que definen una secuencia seq {... }
, list [... ]
o array [|... |]
a través de código que genera valores. Por ejemplo,
seq {} para b dentro 0 .. 25 do si b . 15 entonces rendimiento b*b }
forma una secuencia de cuadrados de números del 0 al 14 filtrando números del rango de números del 0 al 25. Las secuencias son generadores: los valores se generan a pedido (es decir, se evalúan de forma perezosa), mientras que las listas y las matrices son evaluados con entusiasmo.
F# utiliza la coincidencia de patrones para vincular valores a nombres. La coincidencia de patrones también se utiliza cuando se accede a uniones discriminadas: el valor de la unión se compara con las reglas de patrones y se selecciona una regla cuando la coincidencia tiene éxito. F# también admite patrones activos como una forma de coincidencia de patrones extensible. Se utiliza, por ejemplo, cuando existen múltiples formas de hacer coincidir un tipo.
F# admite una sintaxis general para definir cálculos de composición llamada expresiones de cálculo. Las expresiones de secuencia, los cálculos asíncronos y las consultas son tipos particulares de expresiones de cálculo. Las expresiones de cálculo son una implementación del patrón de mónada.
Programación imperativa
La compatibilidad con F# para la programación imperativa incluye
for
bucleswhile
bucles- arrays, creados con los
[|... |]
sintaxis - tabla hash, creado con
dict [... ]
sintaxis oSystem.Collections.Generic.Dictionary
tipo.
Los valores y los campos de registro también se pueden etiquetar como mutable
. Por ejemplo:
// Definir 'x' con valor inicial '1'Deja mutable x = 1// Cambiar el valor de 'x' a '3'x . 3
Además, F# admite el acceso a todos los tipos y objetos de la CLI, como los definidos en el espacio de nombres System.Collections.Generic
que define estructuras de datos imperativas.
Programación orientada a objetos
Al igual que otros lenguajes de infraestructura de lenguaje común (CLI), F# puede usar tipos de CLI a través de la programación orientada a objetos. El soporte de F# para la programación orientada a objetos en expresiones incluye:
- Notación de puntos, por ejemplo,
x.Name
- Expresiones de objetos, por ejemplo,
{ new obj() with member x.ToString() = "hello" }
- Construcción de objetos, por ejemplo,
new Form()
- Pruebas de tipo, por ejemplo,
x :? string
- Introduzca coacción, por ejemplo,
x :?> string
- Nombrados argumentos, por ejemplo,
x.Method(someArgument=1)
- Señales, por ejemplo,
new Form(Text="Hello")
- Discusiones opcionales, por ejemplo,
x.Method(OptionalArgument=1)
La compatibilidad con la programación orientada a objetos en patrones incluye
- Pruebas de tipo, por ejemplo,
:? string as s
- Patrones activos, que pueden definirse sobre tipos de objetos
Las definiciones de tipo de objeto de F# pueden ser definiciones de tipo de clase, estructura, interfaz, enumeración o delegado, correspondientes a los formularios de definición que se encuentran en C#. Por ejemplo, aquí hay una clase con un constructor que toma un nombre y una edad y declara dos propiedades.
// Una definición de tipo objeto simpleTipo Persona()Nombre : cuerda, Edad : int) = miembro x.Nombre = Nombre miembro x.Edad = Edad
Programación asíncrona
F# admite la programación asincrónica a través de flujos de trabajo asincrónicos. Un flujo de trabajo asíncrono se define como una secuencia de comandos dentro de un async{... }
, como en
Deja asynctask = async {} Deja req = WebRequest.Crear()url) ¡Vamos! respuesta = req.GetResponseAsync() uso streaming = respuesta.GetResponseStream() uso streamreader = nuevo Sistema.IO.StreamReader()streaming) retorno streamreader.ReadToEnd() }
El let!
indica que la expresión de la derecha (obtener la respuesta) debe realizarse de forma asincrónica, pero el flujo solo debe continuar cuando el resultado esté disponible. En otras palabras, desde el punto de vista del bloque de código, es como si obtener la respuesta fuera una llamada de bloqueo, mientras que desde el punto de vista del sistema, el subproceso no se bloqueará y puede usarse para procesar otros flujos mientras el resultado necesario para este no esté disponible.
El bloque asíncrono se puede invocar usando la función Async.RunSynchronously
. Se pueden ejecutar múltiples bloques asíncronos en paralelo usando la función Async.Parallel
que toma una lista de objetos async
(en el ejemplo, asynctask
es un objeto asíncrono) y crea otro objeto asíncrono para ejecutar las tareas en las listas en paralelo. El objeto resultante se invoca mediante Async.RunSynchronously
.
La inversión de control en F# sigue este patrón.
Programación paralela
La programación en paralelo se admite en parte a través de Async.Parallel
, Async.Start
y otras operaciones que ejecutan bloques asíncronos en paralelo.
La programación paralela también es compatible a través de los operadores de programación funcional Array.Parallel
en la biblioteca estándar de F#, el uso directo del modelo de programación de tareas System.Threading.Tasks
, el el uso directo del grupo de subprocesos.NET y los subprocesos.NET y mediante la traducción dinámica del código F# a motores alternativos de ejecución en paralelo, como el código GPU.
Unidades de medida
El sistema de tipo F# admite la verificación de unidades de medida para números. La función de unidades de medida se integra con la inferencia de tipo F# para requerir anotaciones de tipo mínimas en el código de usuario.
Metaprogramación
F# permite algunas formas de personalización de sintaxis a través de la metaprogramación para admitir la incorporación de lenguajes específicos de dominio personalizados dentro del lenguaje F#, en particular a través de expresiones de cálculo.
F# incluye una característica para la metaprogramación en tiempo de ejecución llamada cotizaciones. Una expresión de comillas se evalúa como una representación de árbol de sintaxis abstracta de las expresiones de F#. De manera similar, también se puede acceder a las definiciones etiquetadas con el atributo [<ReflectedDefinition>]
en su forma de cotización. Las comillas de F# se utilizan para diversos fines, incluida la compilación de código F# en código JavaScript y GPU. (Las citas representan sus expresiones de código F# como datos para que las usen otras partes del programa y requieren que sea un código F# sintácticamente correcto).
Programación rica en información
F# 3.0 introdujo una forma de metaprogramación en tiempo de compilación a través de la generación de tipo estáticamente extensible denominada proveedores de tipo F#. Los proveedores de tipos de F# permiten que el compilador y las herramientas de F# se amplíen con componentes que proporcionan información de tipo al compilador bajo demanda en el momento de la compilación. Los proveedores de tipo F# se han utilizado para dar acceso fuertemente tipado a fuentes de información conectadas de manera escalable, incluido el gráfico de conocimiento de Freebase.
En F# 3.0, las funciones de expresión de cálculo y cotización de F# se combinan para implementar consultas LINQ. Por ejemplo:
// Utilice el proveedor de tipo OData para crear tipos que puedan utilizarse para acceder a la base de datos Northwind.abierto Microsoft.FSharp.Data.TypeProvidersTipo Northwind = ODataService."http://services.odata.org/Northwind/Northwind.svc"■Deja db = Northwind.GetDataContext()// Una expresión de consulta.Deja query1 = query {} para cliente dentro db.Clientes do seleccionar cliente }
La combinación de proveedores de tipos, consultas y programación funcional fuertemente tipada se conoce como programación rica en información.
Programación de agentes
F# admite una variación del modelo de programación Actor a través de la implementación en memoria de agentes asincrónicos ligeros. Por ejemplo, el siguiente código define un agente y publica 2 mensajes:
Deja contra = MailboxProcessor.Comienzo()diversión Caja - Deja rec bucle n = async {} do printfn "n = %d, esperando..." n ¡Vamos! msg = Caja.Recibido() retorno! bucle()n+msg) } bucle 0)
Herramientas de desarrollo
- Visual Studio, con las herramientas Visual F# de Microsoft instaladas, se puede utilizar para crear, ejecutar y depurar proyectos F#. Las herramientas de Visual F# incluyen una consola interactiva de lectura y impresión (REPL) con sede en Visual Studio que puede ejecutar el código F# como está escrito. Visual Studio for Mac también admite completamente proyectos F#.
- Visual Studio El código contiene soporte completo para F# a través de la extensión Ionide.
- F# se puede desarrollar con cualquier editor de texto. Existe apoyo específico en editores como Emacs.
- JetBrains Rider está optimizado para el desarrollo de código F# comenzando con la versión 2019. 1.
- LINQPad ha apoyado F# desde la versión 2.x.
Áreas de aplicación
F# es un lenguaje de programación de propósito general.
Programación web
SAFE Stack es una pila de F# de un extremo a otro para desarrollar aplicaciones web. Utiliza ASP.NET Core en el lado del servidor y Fable en el lado del cliente.
Una opción alternativa de F# de extremo a extremo es el marco WebSharper.
Desarrollo de aplicaciones multiplataforma
F# se puede usar junto con Visual Studio Tools para Xamarin para desarrollar aplicaciones para iOS y Android. La biblioteca Fabulous proporciona una interfaz funcional más cómoda.
Programación analítica
F#, entre otros, se usa para la programación de finanzas cuantitativas, el comercio de energía y la optimización de carteras, el aprendizaje automático, la inteligencia comercial y los juegos sociales en Facebook.
En la década de 2010, F# se posicionó como una alternativa optimizada a C#. La capacidad de secuencias de comandos de F# y la compatibilidad entre idiomas con todos los productos de Microsoft lo han hecho popular entre los desarrolladores.
Secuencias de comandos
F# se puede utilizar como lenguaje de secuencias de comandos, principalmente para secuencias de comandos de bucle de lectura, evaluación e impresión (REPL).
Comunidad de código abierto
La comunidad de código abierto de F# incluye F# Software Foundation y F# Open Source Group en GitHub. Los proyectos populares de F# de código abierto incluyen:
- Fable, un transpilador F# a Javascript basado en Babel.
- Paket, un gerente de paquete alternativo para. NET que todavía puede utilizar los repositorios NuGet, pero ha centralizado la gestión de versiones.
- FAKE, un sistema de construcción amigable con F#.
- Giraffe, un middleware funcionalmente orientado para ASP. NET Core.
- Suave, un servidor web ligero y una biblioteca de desarrollo web.
Compatibilidad
F# presenta un "modo de compatibilidad de ML" que puede compilar directamente programas escritos en un gran subconjunto de OCaml aproximadamente, sin funtores, objetos, variantes polimórficas u otras adiciones.
Ejemplos
A continuación se muestran algunas pequeñas muestras:
// Este es un comentario para un programa de saludo de muestra.printfn "¡Hola Mundo!"
Una clase Person con un constructor que toma un nombre y una edad y dos propiedades inmutables.
// Este es un comentario de documentación para una definición de tipo.Tipo Persona()Nombre : cuerda, Edad : int) = miembro x.Nombre = Nombre miembro x.Edad = Edad /// instantánea de claseDeja mrSmith = Persona()"Smith", 42)
Un ejemplo simple que se usa a menudo para demostrar la sintaxis de los lenguajes funcionales es la función factorial para enteros no negativos de 32 bits, que se muestra aquí en F#:
// Usando la expresión de ajuste de patrónDeja rec factorial n = partido n con Silencio 0 - 1 Silencio ¿Qué? - n * factorial ()n - 1)// Para las funciones de un solo grupo hay azúcar sintáctica (función de emparejamiento de la máquina):Deja rec factorial = función Silencio 0 - 1 Silencio n - n * factorial ()n - 1) // Utilizando el operador de doble y rangoDeja factorial n = [1..n] ← Seq.plegable (*) 1
Ejemplos de iteraciones:
/// Iteración usando un bucle 'para'Deja printList lst = para x dentro lst do printfn "%d" x/// Iteración utilizando una función de orden superiorDeja printList2 lst = Lista.iter ()printfn "%d") lst/// Iteración utilizando una función y patrón recurrentes que coincidenDeja rec printList3 lst = partido lst con Silencio [] - () Silencio h :: t - printfn "%d" h printList3 t
Ejemplos de Fibonacci:
// Fibonacci Número de fórmulaDeja fib n = Deja rec g n f f1 = partido n con Silencio 0 - f Silencio 1 - f1 Silencio ¿Qué? - g ()n - 1) f1 ()f + f1) g n 0 1// Otro acercamiento - una secuencia infinita perezosa de números FibonacciDeja fibSeq = Seq.desplegable ()diversión ()a,b) - Algunos()a+b, ()b, a+b)) ()0,1)// Imprimir incluso fibs[1 .. 10]← Lista.mapa fib← Lista.filtro ()diversión n - ()n % 2) = 0)← printList// Lo mismo, usando una expresión de lista[ para i dentro 1..10 do Deja r = fib i si r % 2 = 0 entonces rendimiento r ]← printList
Un programa de Windows Forms de muestra:
// Abrir la biblioteca de Windows Formsabierto Sistema.Windows.Forms// Crear una ventana y establecer algunas propiedadesDeja forma = nuevo Formulario()Visible=verdadero, TopMost=verdadero, Texto="Bienvenido a F#")// Crear una etiqueta para mostrar un texto en el formularioDeja etiqueta = Deja x = 3 + ()4 * 5) nuevo Label()Texto = $"{x}")// Añadir la etiqueta al formularioforma.Controles.Añadir()etiqueta)// Por último, ejecute el formulario[.Sistema.STAThread>Aplicación.Corre()forma)
Ejemplo de programación paralela asíncrona (tareas de E/S y CPU paralelas):
// Un simple detector de números primosDeja isPrime ()n:int) = Deja límites = int ()Sqrt ()flotador n) seq {}2 .. límites} ← Seq.para todos ()diversión x - n % x ■ 0)// Estamos usando flujos de trabajo asincDeja primeAsync n = async {} retorno ()n, isPrime n) }// Devolución de primos entre m y n usando múltiples hilosDeja primos m n = seq {}m .. n} ← Seq.mapa primeAsync ← Async.Parallel ← Async.RunSynchronously ← Array.filtro Snd ← Array.mapa f// Ejecutar una pruebaprimos 1000000 1002000 ← Array.iter ()printfn "%d")
Contenido relacionado
Combustión en lecho fluidizado
Modo 13h
Acústica de la sala