Este documento introduce la programación funcional y el lenguaje F#. Explica brevemente qué es la programación funcional, sus ventajas y por qué puede interesar. Luego presenta F# como un lenguaje funcional de Microsoft para .NET, cubriendo sus características como tipado estático, programación asíncrona y paralela. Finalmente, incluye ejemplos de sintaxis, tipos definidos por el usuario, pattern matching y otras construcciones funcionales.
3. ¿QUÉ ES PROGRAMACIÓN FUNCIONAL?
Un paradigma de Programación: Una manera de construir
programas.
Evita cambios de estado. Estructuras de datos inmutables.
No hay asignaciones.
Se utilizan funciones sin efectos laterales: Referencia
transparencial.
Funciones de alto nivel: Aceptan o devuelven funciones.
Las funciones son ciudadanos de primera
clase
4. ¿POR QUÉ ME DEBERÍA INTERESAR LA PROGRAMACIÓN
FUNCIONAL?
La ausencia de efectos laterales implica que es mas simple:
Paralelización
Refactorización
Reutilización
El incremento en número de cores implica la necesidad de
concurrencia.
Lenguajes tradicionalmente imperativos usan
características funcionales, por ejemplo LINQ, Expresiones
Lambda
6. BREVE CONTEXTO HISTÓRICO
En 1970 se desarrolla el lenguaje ML (Meta Language) en la
Universidad de Edinburgh con fines académicos.
Surgen los dialectos CAML (Categorical Abstract Machine
Language) en Francia.
En 2005 Don Syme a través de Microsoft Research
Cambridge publica F# un lenguaje para .NET basado en la
familia de lenguages CAML.
7. ¿POR QUÉ F#?
Interoperable con la plataforma .NET
Multiplataforma
Código Abierto
Conciso
Robusto
Concurrente
Tiene un REPL!
8. CARACTERÍSTICAS PRINCIPALES
Estáticamente tipado con inferencia de tipos
Multiparadigma
Proveedores de tipos: Information Rich Programming
Programación Asíncrona
Programación Paralela
Expresiones Computacionales
10. SINTAXIS E INFERENCIA DE TIPOS
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
let a = 2 // No hay ";"
let b = "hola" // No hay declaración de tipos
let f x = x + 2 // Una función
let f x = x + 2.0
let f x = x + "Hey you"
let f x y = // Parámetros separados por espacios
let z = x**2.0 + y**2.0 // No hay llaves, se utiliza la indenta
ción
sqrt z // Valor de retorno
13. DEFINICIÓN DE TIPOS
Aparte de los tipos básicos
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
type tupla = string*int
type myRegistro = { Nombre:string; Edad:int }
type discriminatedUnion =
| On
| Off
| Inservible of string
type ClasePersona(Nombre:string, Edad:int) =
let mutable peso = 80.0
member this.Nombre = Nombre
member this.Edad = Edad
member this.Peso = peso
member this.GetAñodeNacimiento() = System.DateTime.Now.Year -
Edad
member this.PierdePeso(value) =
peso <- peso - value
peso
14. USO
1:
2:
3:
4:
5:
6:
7:
8:
9:
let valorTupla = "John",14
let valorRegistro = {Nombre="John"; Edad=14}
let valorUnionType = On
let otroValorUnionType = Inservible "quemado"
let instanciaPersona = ClasePersona("John", 14)
16. CURRYING Y APLICACIONES PARCIALES
Currying: Transforma una función con múltiples
argumentos en una función con un argumento
En F# todas las funciones estan currificadas por defecto
Se puede llamar a una función con menos argumentos de
los que espera
Se devuelve una función que acepta los argumentos
restantes
1:
2:
3:
4:
let convierteEuros tasaCambio dinero = dinero * tasaCambio
let convierteEurosADolares = convierteEuros 1.12
let convierteEurosAPesetas = convierteEuros 166.386
17. COMPOSICIÓN
Crear nuevas funciones a partir de otras existentes.
Operador composición:
>>
1:
2:
3:
4:
5:
6:
let grita (s:string) = s.ToUpper()
let exclama s = s + "!"
let anima = exclama >> grita
let textoPancarta = anima "vamos rafa"
"VAMOS RAFA!"
18. PIPELINING
Enlaza la salida de una función con la entrada de otra.
Operador Pipe:
|>
1:
2:
3:
4:
5:
6:
let duplica x = 2 * x
let triplica y = 3 * y
let aplicaOperaciones x = x |> duplica |> triplica |> float |> sqrt
let resultado = aplicaOperaciones 24;;
12.0
19. PROVEEDORES DE TIPOS
PROBLEMAS QUE RESUELVE
Los datos crudos no son tipos
Necesitamos conocer los nombres de las propiedades
Enorme cantidad de fuentes de datos
20. CÓMO
Mapean diferentes fuentes de datos a tipos de F#
Se producen a demanda
Representan las propiedades de los datos
Se adaptan a los cambios de esquema
Ejemplos en las Demos
21. PROGRAMACIÓN ASÍNCRONA
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
open System.Net
open System
open System.IO
let extractLinksAsync html =
async {
return System.Text.RegularExpressions.Regex.Matches(html, @"http
://S+")
}
let downloadAndExtractLinks url =
async {
let webClient = new System.Net.WebClient()
let! html = webClient.AsyncDownloadString(Uri(url))
let! links = extractLinksAsync html
return url,links.Count
}
let links = downloadAndExtractLinks "http://www.google.com/"
let ls = Async.RunSynchronously links
24. CONECTÁNDONOS AL BANCO MUNDIAL EN 5 MINUTOS
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
#r "../packages/FSharp.Data.2.2.5/lib/net40/FSharp.Data.dll"
#load "../packages/FSharp.Charting.0.90.12/FSharp.Charting.fsx"
open FSharp.Data
open FSharp.Charting
let data = WorldBankData.GetDataContext()
let pib = data.Countries.Spain.Indicators.``GDP (constant 2005 US$)``
Chart.Line pib
25. DISEÑO ORIENTADO AL DOMINIO
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
module JuegoCartasBoundedContext =
type Palo = Copas | Bastos | Espadas | Oros
// | significa una elección -- toma uno de la lista
type Valor = Uno | Dos | Tres | Cuatro | Cinco | Seis | Siete
| Sota | Caballo | Rey
type Carta = Palo * Valor // * significa un par -- uno de cada
tipo
type Mano = Carta list
type Baraja = Carta list
type Jugador = {Nombre:string; Mano:Mano}
type Juego = {Baraja:Baraja; Jugadores: Jugador list}
type Reparte = Baraja -> (Baraja * Carta) // X -> Y es una función
// entrada de tipo X
// salida de tipo Y
26. ¿QUÉ FALTA EN ESTE DISEÑO?
¿Qué valores son opcionales, son todos obligatorios?
¿Cuáles son las restricciones?
¿Hay algunos valores que estén relacionados?
¿Hay alguna lógica de dominio que tenga que conocer?
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
type Contact = {
FirstName: string
MiddleInitial: string
LastName: string
EmailAddress: string
IsEmailVerified: bool // true if ownership of email address is confirm
ed
}
27. 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
module ContactExample =
type String1 = String1 of string
type String50 = String50 of string
type EmailAddress = EmailAddress of string
type PersonalName = {
FirstName: String50
MiddleInitial: String1 option
LastName: String50 }
type VerifiedEmail = VerifiedEmail of EmailAddress
type EmailContactInfo =
| Unverified of EmailAddress
| Verified of VerifiedEmail
type Contact = {
Name: PersonalName
Email: EmailContactInfo }