F Sharp (lenguaje de programación)

Ajustar Compartir Imprimir Citar
Microsoft 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.

Resumen de las versiones
Características añadidas
F# 1.0
  • Programación funcional
  • Sindicatos discriminados
  • Documentos
  • Tuples
  • Pattern matching
  • Tipo abreviaturas
  • Programación orientada hacia los objetos
  • Structs
  • Archivos de firma
  • Archivos de scripting
  • Programación imperativa
  • Módulos (sin functores)
  • Módulos anidados
  • . Interoperabilidad NET
F# 2.0
  • Patrones activos
  • Unidades de medida
  • Expresiones de secuencia
  • Programación asincrónica
  • Programación de agentes
  • Miembros de extensión
  • Discusiones designadas
  • Debates facultativos
  • Array slicing
  • Citas
  • Interoperabilidad nativa
  • Expresiones de computación
F# 3.0
  • Proveedores de tipo
  • LINQ query expressions
  • Atributo CLIMutable
  • Cuerdas triples
  • Autopropietarios
  • Unidades de medida
F# 3.1
  • Campos de tipo sindical
  • Extensiones para el corte de matriz
  • Mejoras de la inferencia de tipo
F# 4.0
  • Imprenta sobre valores unificados
  • Iniciadores de propiedades de extensión
  • Tipos no utilizados
  • Constructores primarios como funciones
  • Parámetros estadísticos para los métodos proporcionados
  • Interpolación de imprenta
  • Gramática extendida #if
  • Atributo de Tailcall
  • Múltiples instantáneas de interfaz
  • Args tipo opcional
  • Prótesis
F# 4.1
  • Tuplas filosos que interoperan con tuples C#
  • Anotaciones falsas para los registros
  • Anotaciones fidedignas para Sindicatos Discriminados por Caso Único
  • Subscores en literales numéricos
  • Atributos del argumento info de Caller
  • Tipo de resultado y algunas funciones básicas de resultados
  • Mutually referential types and modules within the same file
  • Sintaxis "Module" implícita en módulos con nombre compartido como tipo
  • Retorno de Byref, soportando métodos de retorno C#
  • Mejoras del mensaje de error
  • Soporte para 'fixed '
F# 4.5
  • Alineación de versiones de binario, paquete y lenguaje
  • Soporte para 'Span seleccionadoT] y tipos relacionados
  • Capacidad para producir retornos 'byref'
  • El tipo 'voidptr'
  • Los tipos de 'inref se hicieron' y 'outref se realizaron''T confía para representar sólo lectura y escritura 'byref's
  • 'IsByRefLike' estructura
  • 'IsReadOnly' structs
  • Soporte de método de extensión para 'byref identificado'Tilo'/'inref seleccionado'T confidencial'/'outref interpretado'T '
  • palabra clave en expresiones de computación
  • Relajado con 'yield' en F# seq/list/array expresiones
  • Indentación relajada con expresiones de lista y array
  • Casos de enumeración emitidos como públicos
F# 4.6
  • Tipos anónimos
F# 4.7
  • Rendimientos implícitos
  • No se necesita más doble subrayado
  • Relajaciones de la indentación para los parámetros pasados a los constructores y métodos estáticos
  • 'nombre de la función
  • Clases estáticas abiertas
F# 5.0
  • FSharp.Core ahora apunta netstandard2.0 sólo
  • Referencias del paquete en scripts F#
  • Soporte para Jupyter, Nteract y VSCode Notebooks
  • Interpolación de cuerdas
  • Apoyo al nombre
  • Declaraciones de tipo abierto
  • Enhanced Slicing
  • Mejoras de las cotizaciones F#
  • Expresiones de computación aplicada
  • Trazas de pila mejoradas en F# async y otras expresiones de computación
  • Mejorado. NET interop
  • Mejorar el rendimiento de Map and Set en FSharp. Core
  • Mejora del rendimiento del compilador
  • Mejor análisis de compiladores para autores de bibliotecas
F# 6.0
  • Tareas
  • Indización más simple
  • Aumentaciones a "tipos activos"
  • Operaciones personalizadas sobrecargadas en expresiones de computación
  • “como” patrones
  • Indentation syntax revisions
  • Conversiones implícitas adicionales
  • Conversiones adicionales implícitas
  • Conversiones implícitas de enteros
  • Apoyo de primera clase. Conversiones implícitas de estilo NET
  • Advertencias opcionales para conversiones implícitas
  • Formato para números binarios
  • Discusiones sobre las uniones de uso
  • InlineIfLambda Optimizr directive
  • Código aplicable
  • Funciones adicionales de colección
  • Mapa tiene claves y valores
  • Intrínseco adicional para NativePtr
  • Tipos numéricos adicionales con anotaciones unitarias
  • Advertencias informativas para operadores simbólicos rara vez utilizados
F# 7.0
  • Los miembros abstractos estáticos apoyan en interfaces
  • Hacer más fácil trabajar con SRTPs (parámetros de tipo estáticamente resueltos)
  • Verificación de propiedades requeridas
  • Alcance de entrada y propiedades únicas
  • Apoyo a las asambleas de referencia
  • F# implementaciones autocontenidas " Native AOT
  • Apoyo adicional para los arrays N-d hasta el rango 32.
  • El módulo Resultado funciona la paridad con Opción.
  • Se fija en el codegen de máquinas estatales resumibles para las tareas construye.
  • Mejor codegen para compiladores de propiedades sin efectos secundarios generados por compiladores
  • ARM64 compilador específico de plataforma y ARM64 soporte de destino en F# compilador. Administrador de dependencia #r soporte de caché
  • Soporte de comprobación y comprobación de proyectos paralelos (experimental, puede ser habilitado a través de configuración VS, o por autores de herramientas)
  • Errores y mejoras diversos.

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:

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

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:

La compatibilidad con la programación orientada a objetos en patrones incluye

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

Á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:

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")