Programacion Funcional en el Mundo Real - Introduccion a F#
-
Upload
roberto-aranda-lopez -
Category
Software
-
view
20 -
download
0
Transcript of Programacion Funcional en el Mundo Real - Introduccion a F#
PROGRAMACIÓN FUNCIONAL EN EL MUNDOREAL
INTRODUCCIÓN A F#
Roberto Aranda López
@glomenar
PROGRAMACIÓN FUNCIONALQué es
Por qué me debería interesar
¿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
¿POR QUÉ ME DEBERÍA INTERESAR LA PROGRAMACIÓNFUNCIONAL?
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
INTRODUCCIÓN A F#
BREVE CONTEXTO HISTÓRICOEn 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.
¿POR QUÉ F#?Interoperable con la plataforma .NET
Multiplataforma
Código Abierto
Conciso
Robusto
Concurrente
Tiene un REPL!
CARACTERÍSTICAS PRINCIPALESEstáticamente tipado con inferencia de tipos
Multiparadigma
Proveedores de tipos: Information Rich Programming
Programación Asíncrona
Programación Paralela
Expresiones Computacionales
ENSÉÑAME EL CÓDIGO
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
Y EL HOLA MUNDO!?
UPS, LO HABÍA OLVIDADO1: printf "Hola Mundo"
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
USO1:
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)
PATTERN MATCHING1:
2:
3:
4:
5:
let enciendeEsteInterruptor unInterruptor =
match unInterruptor with
| On -> "Ya estaba Encendido"
| Off -> "Encendido"
| Inservible s -> "El Interruptor está " + s
CURRYING Y APLICACIONES PARCIALESCurrying: 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
COMPOSICIÓNCrear 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!"
PIPELININGEnlaza 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
PROVEEDORES DE TIPOSPROBLEMAS QUE RESUELVE
Los datos crudos no son tipos
Necesitamos conocer los nombres de las propiedades
Enorme cantidad de fuentes de datos
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
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
PROGRAMACIÓN PARALELA1:
2:
3:
4:
5:
6:
let downloadGoogleLinks = downloadAndExtractLinks "http://www.google.com/"
let downloadWikipediaLinks = downloadAndExtractLinks "http://www.wikipedia.com/"
[downloadGoogleLinks; downloadWikipediaLinks]
|> Async.Parallel
|> Async.RunSynchronously
DEMOS
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
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
type CogeCarta = (Mano * Carta)-> Mano
¿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
}
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 }
NUESTRAS VIEJAS AMIGAS LAS BASES DE DATOS
VOY A MANDAR UN TWEET
¿UNA APLICACIÓN WEB EN F#?
RESUMEN
¿PREGUNTAS?