Translate

Mostrando las entradas con la etiqueta F#. Mostrar todas las entradas
Mostrando las entradas con la etiqueta F#. Mostrar todas las entradas

viernes, 1 de noviembre de 2024

Quicksort en F#


Un Algoritmo que me gusta mucho es el quicksort, porque es un algoritmo por demás claro. Ya he escrito lo fácil que es implementarlo en scalaerlangrusthaskell lisp.

Ahora le toca a F#. Básicamente el algoritmo toma un pivot y agrupa los menores del pivot al principio y los mayores al final y aplica quicksort a estos 2 grupos. Y si la lista es vacía o tiene un elemento, ya esta ordenada. 

Vamos al código:  


let rec quicksort list =

    match list with

    | [] -> []

    | pivot :: tail ->

        let lower = tail |> List.filter (fun x -> x <= pivot)

        let higher = tail |> List.filter (fun x -> x > pivot)

        quicksort lower @ [pivot] @ quicksort higher


viernes, 11 de noviembre de 2022

Microsoft lanza .NET 7



Y porque es tan importante esto?  .NET 7 es una plataforma de desarrollo multiplataforma unificada. 

La idea era unificar .NET Core (reescrito desde cero, open source y multiplataforma) con la tecnología de .NET Framework (más versátil, pero limitada a sistemas Windows), así como con productos como Xamarin y Mono, para crear un producto que permitiera programar sobre una única base de código con runtimes y experiencias de desarrollo uniformes.

Sin embargo, en agosto de 2020, Microsoft anunció que estos pasos se pospondrían hasta el lanzamiento de .NET 6, previsto para noviembre de 2021. Tras eso, la compañía anunció "cambios en el cronograma" que obligaron a postergar de nuevo la integración de componentes como MAUI (Multi-platform App UI). Y así hasta hoy.

Una de las grandes novedades de .NET 7 es la inclusión de la versión 11 de la sintaxis de C#, el lenguaje de programación estrella de Microsoft (F#, también ha sido actualizado).

Además, el anuncio de Microsoft incluye referencias a mejoras de rendimiento, especialmente en ARM64 (con un rendimiento hasta un 45% superior) y acuerdos de colaboración para desarrollar con .NET en Ubuntu Linux, y en los servidores Power System de IBM.

Dejo link : https://news.microsoft.com/es-xl/net-7-esta-disponible-hoy/

martes, 5 de julio de 2022

¿Qué causó el aumento de la popularidad de la programación funcional?



Cuando comencé a dar clases de paradigmas de programación, la programación funcional solo se estudiaba con fines académicos o para la investigación, era poco usado en la industria. Pero esto ha cambiado. La industria ve con buenos ojos a este paradigma y está presente en todos los lenguajes de programación modernos. Para analizar este cambio debemos entender que es la programación funcional. 

 ¿Qué es la programación funcional? 

 Las principales características distintivas del desarrollo de software con Programación funcional son: 

  •     funciones puras; las cuales pueden componer nuevas funciones 
  •     evitar el estado compartido, datos mutables y efectos secundarios; 
  •     La prevalencia de un enfoque declarativo más que imperativo. 

Analicemos estos puntos más en detalle:  

funciones puras: Las funciones puras son funciones deterministas sin efectos secundarios. Una función determinista significa que, para el mismo conjunto de valores de entrada, devuelve el mismo resultado. Las propiedades de tales funciones son muy importantes: por ejemplo, las funciones puras tienen transparencia referencial, se puede reemplazar una llamada de función con su valor final sin cambiar el valor del programa. Y la composición de funciones se refiere al proceso de combinar dos o más funciones para crear una nueva función o realizar cálculos. 

evitar el estado compartido: El principal problema con los estados compartidos es que, para comprender los efectos de una función, debe conocer el historial completo de cada variable compartida que utiliza la función. Por lo tanto, la programación funcional evita estados compartidos, confiando en cambio en estructuras de datos inmutables y computación sin procesar para extraer nuevos datos de los existentes. Otro matiz que surge cuando se trabaja con estados compartidos es que cambiar el orden de las llamadas a funciones puede provocar una avalancha de errores. En consecuencia, al evitar estados compartidos, también evita este problema. 

Subyacente a toda la programación funcional está la inmutabilidad. Los objetos inmutables no se pueden cambiar en absoluto. Esto se logra mediante la congelación profunda de las variables. 

Con estas herramientas se evitan los efectos secundarios, los cuales significan que, además de devolver un valor, la función también interactúa con el estado mutable externo. ¿Por qué Programación funcional los evita? Porque de esta manera los efectos del programa son mucho más fáciles de entender y probar. Haskell, por ejemplo, usa mónadas para aislar los efectos secundarios de las funciones puras. 

enfoque declarativo: El punto es que el enfoque imperativo funciona según el principio de control de flujo y responde a la pregunta "cómo hacerlo". El enfoque declarativo describe el flujo de datos y responde a la pregunta "qué hacer". Además, el código imperativo a menudo se basa en instrucciones (operadores), mientras que el código declarativo se basa en expresiones. 

Ventajas 

Entonces, descubrimos qué es la programación funcional y qué necesitamos saber al respecto. Ahora veamos las ventajas de utilizarlo.   

Uno de los beneficios más obvios de la programación funcional son las abstracciones de alto nivel que ocultan muchos de los detalles de las operaciones de rutina, como la iteración. Debido a esto, el código es más corto y, como resultado, garantiza menos errores que se pueden cometer. 

Además, el Programación funcional contiene menos primitivas de lenguaje. Las clases simplemente no se usan: en lugar de crear una descripción única de un objeto con operaciones en forma de métodos, la programación funcional utiliza varias primitivas básicas del lenguaje que están bien optimizadas internamente. 

Además, la programación funcional permite al desarrollador acercar el lenguaje al problema, en lugar de viceversa, todo a expensas de las estructuras flexibles y la flexibilidad del lenguaje. Además, Programación funcional ofrece a los desarrolladores nuevas herramientas para resolver problemas complejos . 

De hecho, es demasiado largo para enumerar todas las ventajas de la programación funcional; realmente hay muchas de ellas. Puedo decir esto: trabajar con lenguajes funcionales proporciona una escritura de código precisa y rápida, facilita las pruebas y la depuración, los programas son de nivel superior y las firmas de funciones son más informativas. 

La programación funcional permite escribir código más conciso y predecible, y es más fácil de probar (aunque aprender no es fácil). 

Popularidad 

En el mundo de TI, nada sucede porque sí. Una cosa se aferra a la otra, y ahora todas las tendencias más actuales están interconectadas. 

Si recordamos las tendencias más sensacionales de 2016-2017, estas, por supuesto, serán AI, IoT, Big Data y Blockchain. Estaban y están en boca de todos, todos conocen su potencial y sus características claves. Y son algunas de estas tendencias las que han catalizado la creciente popularidad de la programación funcional entre los desarrolladores. 

Actualmente, el problema del procesamiento paralelo y el trabajo con grandes flujos de datos se ha incrementado notablemente. Y, paralelizando el procesamiento de estos datos, podemos obtener el resultado deseado en menor tiempo que con un procesamiento secuencial. Además, la informática descentralizada (distribuida): blockchains y otras, que, en esencia, son un mecanismo bastante complejo. Y para tales cálculos, el código funcional es más adecuado debido a todos los principios de la programación funcional (como las funciones puras, por ejemplo). El uso de todas las técnicas básicas facilita la ejecución y el mantenimiento de código paralelo y distribuido. 

Además, la programación funcional no solo se usaba para resolver problemas específicos, dado el incremento de su popularidad, ahora incluso se aplica a proyectos clásicos.  

Conclusión 

Como probablemente ya haya entendido, no debe temer a la programación funcional.  

 Aquí hay algunos consejos para aquellos que han decidido probarse en un nuevo paradigma y aprender algo radicalmente nuevo: 

Al principio será muy complicado, teniendo en cuenta que tendrás que dejar atrás lo que sabes y aprender nuevos enfoques y principios.  

  • Comience con micro tareas para tenerlo en sus manos. 
  • Si vienes de Java, scala es un gran aleado para empezar, podemos dividir nuestras soluciones y pensar parte en funcional, parte en objeto. Y en .net tenemos F# que es un gran lenguaje.  

La programación funcional tiene un crecimiento constante y es una opción real a problemas que con otros paradigmas no han encontrado una correcta solución.  


martes, 6 de julio de 2021

Web API en F# y .net 5

Vamos a hacer una web Api con F# y Entity Framework. 

Primero hacer la web Api e instalar Entity Framework. 

dotnet new webapi --language "F#"

dotnet add package Swashbuckle.AspNetCore --version 5.6.3

dotnet new tool-manifest

dotnet tool install dotnet-ef

dotnet tool install paket

dotnet paket convert-from-nuget

dotnet paket add Microsoft.EntityFrameworkCore.Sqlite

dotnet paket add EntityFrameworkCore.FSharp

code  .


Ahora creamos el modelo: 

Hice un archivo Prueba.fs : 

namespace webAPIFsharp

open System

[<CLIMutable>]
type Prueba =
{ Id: int
Name : string
Summary: string }

Y hacemos el dbcontext : 

namespace webAPIFsharp

open System.ComponentModel.DataAnnotations
open Microsoft.EntityFrameworkCore
open EntityFrameworkCore.FSharp.Extensions

type ApiDbContext() =
inherit DbContext()

[<DefaultValue>]
val mutable pruebas : DbSet<Prueba>

member public this.Pruebas with get() = this.pruebas
and set p = this.pruebas <- p

override _.OnModelCreating builder =
builder.RegisterOptionTypes() // enables option values for all entities

override __.OnConfiguring(options: DbContextOptionsBuilder) : unit =
options.UseSqlite("Data Source=base.db") |> ignore

Ahora debemos indicar que compile estas clases agregando estas entradas en el fsproj : 

<Compile Include="Prueba.fs" />
<Compile Include="ApiDbContext.fs" />

Luego compilamos 

dotnet build

Si funciona debemos hacer la migración : 

dotnet ef migrations add Initial

Y ahora agregamos la migración a fsproj :

<Compile Include="Migrations/*.fs" />

Y ahora creamos la base : 

dotnet ef database update

Y ahora agregamos el context a el Startup.fs : 

// Configure EF
services.AddDbContext<ApiDbContext>() |> ignore

Y luego hacemos el controler : 

namespace webAPIFsharp.Controllers

open System
open System.Collections.Generic
open System.Linq
open System.Threading.Tasks
open Microsoft.EntityFrameworkCore
open Microsoft.AspNetCore.Mvc
open Microsoft.Extensions.Logging
open webAPIFsharp

[<ApiController>]
[<Route("[controller]")>]
type PruebaController (logger : ILogger<PruebaController>,
dbContext : ApiDbContext) =
inherit ControllerBase()


[<HttpGet>]
member _.Get() = ActionResult<IEnumerable<Prueba>>(dbContext.Pruebas)

[<HttpPost>]
member _.PostSync(prueba:Prueba) =
dbContext.Pruebas.Add prueba |> ignore
dbContext.SavedChanges |> ignore


[<HttpPost("async")>]
member _.PostAsync(entity: Prueba) =
async {
dbContext.Pruebas.AddAsync(entity) |> ignore
let! _ = dbContext.SaveChangesAsync true |> Async.AwaitTask
return entity
}

[<HttpGet("{id}")>]
member _.getById id =
dbContext.Pruebas
|> Seq.tryFind (fun f -> f.Id = id)

Y listo! 

dotnet run

Yo agregue swagger para mayor detalles dejo link de github: 

https://github.com/emanuelpeg/FsharpWebApiExample


lunes, 3 de mayo de 2021

Primera Aplicación en .net 5 en F#


Vamos rapidito, antes que nada tenemos que tener .net instalado y visual code (con el plugin de F#)

Y luego creamos una carpeta y hacemos una aplicación de consola: 

mkdir miPrimerApp

cd miPrimerApp

dotnet new console -lang "F#"

code .

Como verán le puse miPrimerApp a la carpeta y luego ejecute visual code con el comando "code ."

En visual code podemos ver la clase Program.fs que se va a ejecutar : 

// Learn more about F# at http://docs.microsoft.com/dotnet/fsharp

open System

// Define a function to construct a message to print
let from whom =
sprintf "from %s" whom

[<EntryPoint>]
let main argv =
let message = from "F#" // Call the function
printfn "Hello world %s" message
0 // return an integer exit code

Buenisimo, ya casi estamos, ahora podemos ejecutarlo desde la consola con : 

$ dotnet run
Hello world from F#

o con visual code desde "run -> start debugging" 


martes, 23 de marzo de 2021

Arquitectura de .NET Framework

Los dos componentes principales de .NET Framework son Common Language Runtime y .NET Framework Class Library.

Common Language Runtime (CLR) es el motor de ejecución que maneja las aplicaciones en ejecución. Proporciona servicios como administración de subprocesos, recolección de basura, seguridad de tipos, manejo de excepciones y más.

La biblioteca de clases proporciona un conjunto de API y tipos para una funcionalidad común. Proporciona tipos de cadenas, fechas, números, etc. La biblioteca de clases incluye API para leer y escribir archivos, conectarse a bases de datos, dibujar y más.

Las aplicaciones .NET están escritas en lenguaje de programación C#, F# o Visual Basic. El código se compila en un Lenguaje Intermedio Común (CIL) independiente del lenguaje. El código compilado se almacena en ensamblados: archivos con una extensión de archivo .dll o .exe.

Cuando se ejecuta una aplicación, CLR toma el ensamblado y usa un compilador just in time (JIT) para convertirlo en código de máquina que se puede ejecutar en la arquitectura específica de la computadora en la que se está ejecutando.

viernes, 28 de agosto de 2020

Que lenguaje de programación debo aprender?


Este es un post de opinión no me apoyo en ninguna encuesta o nada, es opinión de lo que voy leyendo. A la vez ya hice post similares pero lo actualice a 2020. 

Dicho esto, me pongo a opinar. Si queres aprender un lenguaje de programación, lo que primero que debes hacer es pensar a que te queres dedicar. Dado que la programación tiene varios objetivos y si bien hay lenguajes que son buenos para todo pero no son populares en todo, por lo tanto, dependiendo a que te queres dedicar es el lenguaje que debes aprender. 

Voy a listar temas y poniendo los lenguajes. 

Backend : Java, C#, Kotlin, Scala, Groovy, PHP, Python, Haskell, Go, SQL, Ruby

Frontend : Javascript, Typescript, Elm

Mobile : Java, Kotlin, C#, Dart

Data science : SQL, Python, Julia, R

Sistemas (bajo nivel) : Rust, Go, C

Sistemas concurrentes : Rust, Go, Scala, Haskell, Erlang, Elixir

Juegos : C, C++, Rust, Go, Lua, Elm, C#



lunes, 1 de junio de 2020

repl.it, Una super IDE online


repl.it es un IDE gratuito, colaborativo y en el navegador para codificar en más de 50 lenguajes, sin gastar un segundo en la configuración.

Les cuento, quería probar algo en Haskell y me encontré con esta joya. Esta muy bueno, te haces un usuario si queres, codeas y si configuraste un repo en github te guarda los archivos ahí. Podes compartir codigo, trabajar en equipo...

Podes programar en : 

Python, Nodejs, C, Java, C++, Ruby, HTML, CSS, JS, Lisp, Go, Rust, Roy, kotlin, Swift, F#, C#, etc...

Punto bajo, no permite ni Scala, ni Grovyy... 


Dejo link: https://repl.it/

lunes, 9 de marzo de 2020

HTML + javascript + Haskell = ELM, parte 4


Seguimos con el post anteriro.

Como con cualquier lenguaje funcional, la base de Elm es la función. Definir una es trivial. Veamos algunas funciones :

> add x y = x + y
<function> : number -> number -> number
> double x = x * 2
<function> : number -> number
> anonymousInc = \x -> x + 1
<function> : number -> number
> double (add 1 2)
6 : number
> List.map anonymousInc [1, 2, 3]
[2,3,4] : [number]

La sintaxis para crear funciones es muy simple e intuitiva. add es una función con nombre con dos argumentos, x e y. Las funciones anónimas expresan parámetros como \ x, y el cuerpo de la función sigue los caracteres ->.
Como Elixir, Elm tiene el operador de tubería que permite componer funciones, de esta manera:


Tomamos 5 y lo pasamos como el primer argumento a anonymousInc, para obtener 6. Luego, lo pasamos como el primer argumento para duplicar. También podemos hacer que esa expresión se ejecute de derecha a izquierda:

> double <| anonymousInc <| 5
12 : number

Evan Czaplicki, creador de Elm, dice que obtuvo esta función de F#, que a su vez obtuvo la idea de las tuberías de Unix, por lo que esta idea ha existido por un tiempo, ¡pero es buena!
Al igual que con cualquier lenguaje funcional, hay muchas funciones que le permitirán trabajar con funciones de todo tipo de formas:

> List.map double [1..3]
[2,4,6] : List number
> List.filter (\x -> x < 3) [1..20]
[1,2] : List comparable

[1..3] es un rango. Puede explorar más funciones de la Lista con la biblioteca de listas.

Cuando está componiendo una solución con Elm, puede tener la tentación de codificar cada caso como un cuerpo de función separado como lo haría en Haskell, Erlang o Elixir, pero no se puede :( :

> factorial 1 = 1
<function> : number -> number'
> factorial x = x * factorial (x - 1)
<function> : number -> number
RangeError: Maximum call stack size exceeded

Parece que la segunda llamada reemplazó a la primera. En cambio, debe usar el mismo cuerpo de función y dividir el problema usando mayúsculas y minúsculas o si, de esta manera:

> factorial x = \
|  if | x == 0 -> 1 \
|      | otherwise -> x * factorial (x - 1)
<function> : number -> number
> factorial 5
120 : number

Suficientemente simple. factorial 0 es 1; de lo contrario, factorial x es x * factorial (x-1). Manejaría la recursividad de la lista de la misma manera:

> count list = \
| case list of \
| [] -> 0 \
| head::tail -> 1 + count tail
<function> : [a] -> number
> count [4, 5, 6]
3 : number

La cantidad de elementos de una lista vacía es cero y la cantidad de elementos de cualquier otra lista es 1 más la cantidad del resto. Veamos cómo atacar problemas similares con la coincidencia de patrones.

Por ahora vamos bien, pero seguimos en otro post... 


sábado, 2 de noviembre de 2019

Resultados de la encuesta de Stackoverflow 2019



Stackoverflow publico los resultados de su encuesta 2019, la verdad todo normal nada que me llame la atención excepto:


  • Lenguaje más amado Rust, ya me tengo que poner a estudiar este lenguaje. 
  • Lenguajes mejor pagos, del top 5, 4 son funcionales. Así que es buena idea aprender programación funcional. 




Dejo link : https://insights.stackoverflow.com/survey/2019

miércoles, 1 de mayo de 2019

C# y F# para Apache Spark


Microsoft anunció el lanzamiento de .NET para Apache Spark.

Microsoft anunció la versión preliminar de .NET para Apache Spark. Apache Spark está escrito en Scala, por lo que siempre ha tenido soporte nativo para este lenguaje. También ha tenido durante mucho tiempo enlaces API para Java, así como los populares lenguajes de ciencia de datos Python y R. Los nuevos enlaces de lenguaje para C# y F# están escritos en una nueva capa de interoperabilidad Spark. En las pruebas en el punto de referencia TPC-H, el rendimiento de .NET fue comparable a otros lenguajes, y en algunos casos fue "2 veces más rápido que Python".

Los desarrolladores pueden reutilizar el código y las librerías compatibles con .NET estándar y "pueden acceder a todos los aspectos de Apache Spark, incluidos Spark SQL, DataFrames, Streaming, MLLib". Los desarrolladores de la nube pueden implementar .NET para Apache Spark en Azure de Microsoft usando Azure HDInsight y Azure Databricks, o en Amazon Web Services usando Amazon EMR Spark y AWS Databricks.

La ejecución de aplicaciones .NET en Spark requiere la instalación de los binarios de Microsoft.Spark.Worker, así como un JDK y los binarios estándar de Apache Spark. El desarrollo de una aplicación requiere la instalación del paquete nuget Microsoft.Spark. Los desarrolladores de Microsoft han enviado Propuestas de mejora de proyectos Spark (SPIP) para incluir la extensión de lenguaje C# y una capa de interoperabilidad genérica en Spark. Sin embargo, Sean Owen, un comentarista de Apache Spark, comentó que sería "altamente improbable" que el trabajo se fusionara con Spark.

La hoja de ruta de .NET para Apache Spark enumera varias mejoras al proyecto que ya está en marcha, incluida la compatibilidad con Apache Spark 3.0, la compatibilidad con la vectorización de .NET Core 3.0 y la compatibilidad con VS Code. .NET para el código fuente de Apache Spark está disponible en Github.

sábado, 6 de abril de 2019

Tipos que pueden ser referencia a nulos en F# 5

La introducción de tipos que pueden ser referencia a nulos en en C # representa el mayor cambio en la forma en que los desarrolladores de .NET escriben código desde async / await. Una vez que esté en funcionamiento, se tendrán que actualizar innumerables bibliotecas con anotaciones que admiten nulos para que esta característica funcione correctamente. Y para garantizar la interoperabilidad, F # deberá tambien modificarse.

F# actualmente soporta varias versiones de nulabilidad. Primero hay tipos normales de referencia en .NET. Hoy en día no hay manera de informar inequívocamente al compilador si una variable de tipo de referencia específica es nullable o no, por lo que se desaconseja su uso en F #.

La alternativa preferida es la Option<T>. También conocido como un tipo de "tal vez", esta es una forma segura para expresar el concepto de nulabilidad. Cuando se usa con el código F # idiomático, solo puede leer el valor después de verificar si no es nulo (no es "ninguno" en el lenguaje F #). Esto generalmente se hace a través de la comparación de patrones. Por ejemplo,

match ParseDateTime inputString with
| Some(date) -> printfn "%s" (date.ToLocalTime().ToString())
| None -> printfn "Failed to parse the input."

Option<T> es un tipo de referencia. Esto puede llevar a una gran cantidad de uso de memoria innecesaria, por lo que se creó una alternativa basada en estructura llamada ValueOption<T> en F # 4.5. Sin embargo, a ValueOption<T> le faltan algunas características que no estarán completas hasta que se lance F # 4.6.

Otro tipo de null F # con el que los desarrolladores deben tratar es Nullable<T>. Esto es similar a ValueOption<T>, pero está restringido a solo tipos de valor.

Las clases también se pueden marcar como nullables. Si el tipo tiene el atributo AllowNullLiteral, entonces todas las variables de ese tipo se consideran nullables. Esto puede ser problemático cuando desea que algunas variables de ese tipo sean nullables, pero no otras.

Un problema fundamental de diseño con F # tal como se encuentra actualmente es que todas estas formas diferentes de nulabilidad son incompatibles. No solo se necesitan conversiones entre los diferentes tipos de nulos, sino que también existen diferencias importantes en la forma en que funcionan. Por ejemplo, una  Option<T> es recursiva, lo que le permite tener una Option<Option<Int32>> mientras que Nullable<T> no lo es. Esto puede llevar a problemas inesperados cuando se mezclan.

Otra forma en que esta incompatibilidad entra en juego es el atributo CLIMutable. Normalmente, los tipos de registro son inmutables, pero eso los hace incompatibles con los ORM. Este atributo soluciona ese problema, pero introduce uno nuevo. Ahora que el registro es mutable, los nulos se pueden deslizar después de crear el objeto, rompiendo la suposición de que los registros no contienen nulos.

El plan actual es indicar variables anulables con un ? sufijo como vemos en C#. Y al igual que C# 8, recibirá advertencias si intenta invocar un método o una propiedad en una variable que puede contener nulos sin verificar primero si es nulo. Del mismo modo, la asignación de un valor nulo a una variable no anulable es solo una advertencia, por lo que el código heredado continúa compilando.

Esta funcionalidad se considera como opt-in. Los nuevos proyectos lo tendrán activado de forma predeterminada, mientras que los proyectos existentes lo desactivarán de forma predeterminada.

Los ejemplos a continuación fueron proporcionados por la propuesta de Tipos de Referencia de Nullable y están sujetos a cambios.

// Declared type at let-binding
let notAValue : string? = null

// Declared type at let-binding
let isAValue : string? = "hello world"
let isNotAValue2 : string = null // gives a nullability warning
let getLength (x: string?) = x.Length // gives a nullability warning since x is a nullable string

// Parameter to a function
let len (str: string?) =
match str with
| null -> -1
| NonNull s -> s.Length // binds a non-null result

// Parameter to a function
let len (str: string?) =
let s = nullArgCheck "str" str // Returns a non-null string
s.Length // binds a non-null result

// Declared type at let-binding
let maybeAValue : string? = hopefullyGetAString()

// Array type signature
let f (arr: string?[]) = ()

// Generic code, note 'T must be constrained to be a reference type
let findOrNull (index: int) (list: 'T list) : 'T? when 'T : not struct =
match List.tryItem index list with
| Some item -> item
| None -> null

Como puede ver, la nueva sintaxis se adapta bien a los patrones F # existentes, incluso admite la coincidencia de patrones de manera similar a la  Option<T>.

También hay un conjunto de funciones de ayuda para agregar en el código general y la coincidencia de patrones.

isNull: determina si el valor dado es nulo.
nonNull: afirma que el valor no es nulo. Provoca una NullReferenceException cuando el valor es nulo, de lo contrario, devuelve el valor.
withNull: convierte el valor en un tipo que admite nulo como un valor normal.
(| NonNull |): cuando se usa en un patrón, se afirma que el valor que se compara no es nulo.
(| Null | NotNull |): Un patrón activo que determina si el valor dado es nulo.
Las firmas de funciones completas están disponibles en la propuesta.


sábado, 13 de enero de 2018

Comparando F# con C# parte 3

Vamos ha hacer un programa que baje una pagina en F# y en C# para comparar.

Veamos la implementación en F# :

// open es similar al using
open System.Net
open System
open System.IO

// Obtener los contenidos de una página web
let fetchUrl callback url =     
    let req = WebRequest.Create(Uri(url))
    use resp = req.GetResponse()
    use stream = resp.GetResponseStream()
    use reader = new IO.StreamReader(stream)
    callback reader url

Repasemos este código:

  • El "open" en la parte superior nos permite escribir "WebRequest" en lugar de "System.Net.WebRequest". Es similar a un encabezado "using System.Net" en C#.
  • A continuación, definimos la función fetchUrl, que toma dos argumentos, un callback para procesar la pagina y la URL a buscar.
  • Luego, creamos una Uri con la URL. F# tiene una estricta comprobación de tipos, por lo tanto, si en  hubiéramos escrito: let req = WebRequest.Create(url), el compilador se habría quejado de que no sabía qué versión de WebRequest.Create usar.
  • Al declarar los valores de respuesta, transmisión y lectura, se usa la palabra clave "use" en lugar de "let". Esto solo se puede usar junto con las clases que implementan IDisposable. Le dice al compilador que elimine automáticamente el recurso cuando se sale del alcance. Esto es equivalente a la palabra clave "using" C#.
  • La última línea llama a la función callback con StreamReader y la url como parámetros. Note que nunca especificamos el timpo del callback. 


Ahora veamos la implementación equivalente de C#:

class WebPageDownloader
{
    public TResult FetchUrl<TResult>(
        string url,
        Func<string, StreamReader, TResult> callback)
    {
        var req = WebRequest.Create(url);
        using (var resp = req.GetResponse())
        {
            using (var stream = resp.GetResponseStream())
            {
                using (var reader = new StreamReader(stream))
                {
                    return callback(url, reader);
                }
            }
        }
    }
}

Como de costumbre, la versión C # tiene más 'ruido'.

  • Hay diez líneas solo para llaves, y existe la complejidad visual de 5 niveles de anidación *
  • Todos los tipos de parámetros deben declararse explícitamente, y el tipo TResult genérico debe repetirse tres veces.
Podemos probar el codigo de la siguiente manera : 


let myCallback (reader:IO.StreamReader) url = 
    let html = reader.ReadToEnd()
    let html1000 = html.Substring(0,1000)
    printfn "Downloaded %s. First 1000 is %s" url html1000
    html      // return all the html

//test
let google = fetchUrl myCallback "http://google.com"

Finalmente, tenemos que recurrir a una declaración de tipo para el parámetro del lector (reader:IO.StreamReader). Esto es necesario porque el compilador F# no puede determinar el tipo del parámetro "reader" automáticamente.

Una característica muy útil de F# es que puede "pasar" parámetros en una función para que no tengan que pasarse en todo momento. Esta es la razón por la que el parámetro url se colocó en último lugar en lugar de primero, como en la versión de C#. La devolución de llamada se puede configurar una vez, mientras que la URL varía de llamada a llamada.

// build a function with the callback "baked in"
let fetchUrl2 = fetchUrl myCallback 

// test
let google = fetchUrl2 "http://www.google.com"
let bbc    = fetchUrl2 "http://news.bbc.co.uk"

// test with a list of sites
let sites = ["http://www.bing.com";
             "http://www.google.com";
             "http://www.yahoo.com"]

// process each site in the list
sites |> List.map fetchUrl2 

La última línea (usando List.map) muestra cómo la nueva función se puede usar fácilmente junto con las funciones de procesamiento de listas para descargar una lista completa a la vez.

Aquí está el código de prueba C# equivalente:

[Test]
public void TestFetchUrlWithCallback()
{
    Func<string, StreamReader, string> myCallback = (url, reader) =>
    {
        var html = reader.ReadToEnd();
        var html1000 = html.Substring(0, 1000);
        Console.WriteLine(
            "Downloaded {0}. First 1000 is {1}", url,
            html1000);
        return html;
    };

    var downloader = new WebPageDownloader();
    var google = downloader.FetchUrl("http://www.google.com",
                                      myCallback);
            
    // test with a list of sites     var sites = new List<string> {
        "http://www.bing.com",
        "http://www.google.com",
        "http://www.yahoo.com"};

    // process each site in the list   
   sites.ForEach(site => downloader.FetchUrl(site, myCallback));
}

De nuevo, el código tiene más ruido que el código F#, con muchas referencias explícitas de tipo. Lo que es más importante, el código C# no le permite pasar fácilmente algunos de los parámetros en una función, por lo que la devolución de llamada se debe referenciar explícitamente cada vez.



miércoles, 3 de enero de 2018

Comparando F# con C# parte 2



Ahora, implementaremos un el algoritmo quicksort para ordenar listas y lo haremos en F# y C# para compararlos.

Para el que no conoce el algoritmo quicksort, vamos a ver la lógica:

Si la lista está vacía, no hay nada que hacer.
De otra manera:
  1. Tome el primer elemento de la lista, que lo llamaremos pivot
  2. Buscamos todos los elementos menores al pivot y los ordenamos usando el algoritmo quicksort.
  3. Buscamos todos los elementos mayores al pivot y los ordenamos usando el algoritmo quicksort.
  4. Combinamos las tres partes para obtener el resultado final: (elementos menores + pivot + elementos mayores)
Tenga en cuenta que hemos simplificado este algoritmo para hacer la explicación más simple.

Veamos el código en F#:

let rec quicksort list =
   match list with
   | [] ->                            // Si la lista es vacia
        []                            // retorna una lista vacia
   | firstElem::otherElements ->      // si no es vacia
        let smallerElements =         // toma los menores
            otherElements             
            |> List.filter (fun e -> e < firstElem) 
            |> quicksort              // y los ordena
        let largerElements =          // toma los mayores 
            otherElements 
            |> List.filter (fun e -> e >= firstElem)
            |> quicksort              // y los ordena
        // concatena estas 3 partes y la retorna. 
        List.concat [smallerElements; [firstElem]; largerElements]

//test
printfn "%A" (quicksort [1;5;23;18;9;1;3])

Repasemos el código:

No hay declaraciones de tipos en ningún lado. Esta función funcionará en cualquier lista que tenga elementos comparables (que es casi todos los tipos F#, ya que automáticamente tienen una función de comparación predeterminada).
Toda la función es recursiva: esto se señala al compilador utilizando la palabra clave rec en "let rec quicksort list =".
Con  match..with se esta usando pattern matching, las expresiones son como esta:

match x with
| caseA -> something
| caseB -> somethingElse

El pattern matching es una técnica que analiza objetos y ejecuta el código que corresponde (cuando el objeto aplica le patron)

De esta manera se pregunta si la lista es vacía, y si es vacía se retorna una lista vacía.
De lo contrario, aplica la lógica descrita anteriormente. Es decir filtra la lista de los menores por medio de una función anónima que se pasa como clausura, que indica como se va a filtrar y luego se ordena utilizando quicksort, luego filtra la lista de los mayores y los ordena .  Y por ultimo se retorna la concatenación de estas 3 partes.                                                                                                     ,

Veamos la implementación en C# sin LinQ :

public class QuickSortHelper
{
   public static List<T> QuickSort<T>(List<T> values)
      where T : IComparable
   {
      if (values.Count == 0)
      {
         return new List<T>();
      }
     // Tomamos el primer valor
     T firstElement = values[0];
     // Filtramos los elementos
      var smallerElements = new List<T>();
      var largerElements = new List<T>();

      for (int i = 1; i < values.Count; i++)   {
 
         var elem = values[i];
 
         if (elem.CompareTo(firstElement) < 0)
         {
            smallerElements.Add(elem);
         }
         else
         {
            largerElements.Add(elem);
         }
      }

      result.AddRange(QuickSort(smallerElements.ToList()));
      result.Add(firstElement);
      result.AddRange(QuickSort(largerElements.ToList()));
      return result;
   }
}

Comparando los dos programas, nuevamente podemos ver que el código F# es mucho más compacto, con menos ruido y sin necesidad de declaraciones de tipo.

Además, el código F# se lee casi exactamente como es algoritmo, a diferencia del código C#. Esta es otra ventaja clave de F# - el código es generalmente más declarativo ("qué hacer") y menos imperativo ("cómo hacerlo") que C#, y por lo tanto es mucho más autodocumentado.

Veamos una versión más funcional en C#:

public static class QuickSortExtension
{
     public static IEnumerable<T> QuickSort<T>(
        this IEnumerable<T> values) where T : IComparable
    {
        if (values == null || !values.Any())
        {
            return new List<T>();
        }

        var rest = values.Skip(1);
                .Where(i => i.CompareTo(firstElement) < 0)
                .QuickSort();

        var largerElements = rest
                .Where(i => i.CompareTo(firstElement) >= 0)
                .QuickSort();
     
        return smallerElements
            .Concat(new List<T>{firstElement})
            .Concat(largerElements);
    }
}

Esto es mucho más limpio, y lee casi lo mismo que la versión F#.

Finalmente, el código F# a menudo funciona la primera vez, mientras que el código C# puede requerir más depuración.

Pero incluso la ultima versión funcional C# tiene inconvenientes en comparación con la versión F#. Por ejemplo, como F# usa la coincidencia de patrones, no es posible derivar al caso de la "lista no vacía" con una lista vacía.

Dejo link: https://fsharpforfunandprofit.com/posts/fvsc-quicksort/


viernes, 29 de diciembre de 2017

Comparando F# con C#


Vamos a comparar C# con F# a traves de un ejemplo, una suma simple. El problema es simple: "sumar los cuadrados de 1 a N".

Primero, veamos el código F# :

// define the square function
let square x = x * x

// define the sumOfSquares function
let sumOfSquares n =
   [1..n] |> List.map square |> List.sum

// try it
sumOfSquares 100

Y listo, como podemos ver podemos utilizar el operador |> para que la salida de una función, sea entrada de otra. Es similar a el operador |> de elixir.

Si vemos la linea: let sumOfSquares n = [1..n] |> List.map square |> List.sum

  1. Crea una lista de enteros de 1 a n. 
  2. Luego toma esa lista y aplica una función square usando la biblioteca llamada List.map.
  3. Luego acumula todos los elementos de la lista resultante. 

Ahora veamos una implementación en C# utilizando el estilo clásico (no funcional) :

public static class SumOfSquaresHelper
{
   public static int Square(int i)
   {
      return i * i;
   }

   public static int SumOfSquares(int n)
   {
      int sum = 0;
      for (int i = 1; i <= n; i++)
      {
         sum += Square(i);
      }
      return sum;
   }
}

¿Cuáles son las diferencias?

  • El código F# es más compacto
  • El código F# no tenía ninguna declaración de tipo
  • Con F# podemos desarrollar interactivamente

La diferencia más obvia es que hay mucho más código C#. 13 líneas en C# en comparación con 3 líneas en F# (ignorando los comentarios). El código C# tiene mucho "ruido", cosas como llaves, puntos y comas, etc. Y en C# las funciones no pueden estar solas, sino que deben agregarse a alguna clase ("SumOfSquaresHelper"). F# usa espacios en blanco en lugar de paréntesis, no necesita terminador de línea y las funciones pueden ser independientes.

En F#, es común que las funciones completas se escriban en una línea, como la función "cuadrada". La función sumOfSquares también podría haber sido escrita en una línea. En C# esto es mal visto y es considerado una mala práctica.

Cuando una función tiene múltiples líneas, F# usa indentación para indicar un bloque de código, lo que elimina la necesidad de llaves. (Si alguna vez ha usado Python, esta es la misma idea). Entonces la función sumOfSquares también podría haber sido escrita de esta manera:

let sumOfSquares n = 
   [1..n] 
   |> List.map square 
   |> List.sum

La siguiente diferencia es que el código C# tiene que declarar explícitamente todos los tipos utilizados. Por ejemplo, el parámetro n es de tipo int y el tipo de retorno SumOfSquares es int. Sí bien, C# permite usar la palabra clave "var" en muchos lugares, pero no para los parámetros y tampoco para tipos de funciones.

En el código F#, no declaramos ningún tipo. Este es un punto importante: F# parece un lenguaje sin tipo o de tipado dinámico, pero en realidad es igual de seguro que C#, de hecho, ¡aún más! F# usa una técnica llamada "inferencia de tipo" para inferir los tipos que está utilizando desde su contexto. Funciona increíblemente bien la mayor parte del tiempo, y reduce la complejidad del código inmensamente.

En este caso, el algoritmo de inferencia de tipo observa que comenzamos con una lista de enteros. Esto a su vez implica que la función cuadrada y la función suma también deben tomarse, y que el valor final debe ser un int. Puede ver cuáles son los tipos inferidos mirando el resultado de la compilación en la ventana interactiva. Verás algo como:

val square : int -> int

lo que significa que la función "cuadrado" toma un int y devuelve un int. Esta notación me recuerda mucho a Haskell o Scala.

Si la lista original hubiera utilizado flotantes en su lugar, el sistema de inferencia tipo habría deducido que la función cuadrada utilizada flotantes en su lugar:

// define the square function
let squareF x = x * x

// define the sumOfSquares function
let sumOfSquaresF n = 
   [1.0 .. n] |> List.map squareF |> List.sum  // "1.0" is a float

sumOfSquaresF 100.0

¡La verificación de tipos es muy estricta! Si intenta usar una lista de flotantes ([1.0..n]) en el ejemplo original sumOfSquares, o una lista de ints ([1 ..n]) en el ejemplo sumOfSquaresF, obtendrá un error de tipo del compilador.

Finalmente, F# tiene una ventana interactiva donde puedes probar el código inmediatamente y jugar con él. En C# no hay una manera fácil de hacer esto.

Por ejemplo, puedo escribir mi función cuadrada e inmediatamente probarla:

// define the square function
let square x = x * x

// test
let s2 = square 2
let s3 = square 3
let s4 = square 4

Muchas personas afirman que el diseño de códigos impone de forma interactiva buenas prácticas de diseño, como el desacoplamiento y las dependencias explícitas, y por lo tanto, el código que es adecuado para la evaluación interactiva también será un código que es fácil de probar. Por el contrario, el código que no se puede probar de forma interactiva probablemente también sea difícil de probar.

El ejemplo anterior fue escrito usando C# viejo. C# ha incorporado muchas características funcionales, y es posible reescribir el ejemplo de una manera más compacta utilizando las extensiones LINQ.

Así que aquí hay otra versión C#: 

public static class FunctionalSumOfSquaresHelper
{
   public static int SumOfSquares(int n)
   {
      return Enumerable.Range(1, n)
         .Select(i => i * i)
         .Sum();
   }
}

Sin embargo, además del ruido de las llaves, los puntos y los puntos y comas, la versión C# necesita declarar el parámetro y los tipos de retorno, a diferencia de la versión F#.

Si bien el ejemplo fue trivial, nos permitio revisar las deferencias entre F# y C#.

Dejo link: https://fsharpforfunandprofit.com/posts/fvsc-sum-of-squares//



sábado, 16 de diciembre de 2017

Primeros pasos con F#

Si bien hemos hablado de F# en el blog nunca hice un post del lenguaje en si, bueno vamos a cambiar eso.

Si vamos a la pagina de F# nos dira que es un lenguaje open source, multiplataforma y funcional. Capaz de resolver problemas complejos de forma simple.

Por que utilizar o aprender F#?

  • Concisión. F # no está lleno de "ruido" de codificación, como llaves, punto y coma, etc. Casi nunca tiene que especificar el tipo de un objeto, gracias a un potente sistema de inferencia de tipo. Y generalmente requiere menos líneas de código para resolver el mismo problema.
  • Conveniente. Muchas tareas de programación comunes son mucho más simples en F#. Esto incluye cosas como crear y usar definiciones de tipos complejos, hacer el procesamiento de listas, comparación e igualdad, máquinas de estado y mucho más. Y debido a que las funciones son objetos de primera clase, es muy fácil crear código poderoso y reutilizable creando funciones que tienen otras funciones como parámetros, o que combinan funciones existentes para crear nuevas funcionalidades.
  • Exactitud. F# tiene un sistema de tipo muy poderoso que evita muchos errores comunes, como las excepciones de referencia nula. Además, a menudo puede codificar la lógica de negocios utilizando el sistema de tipo en sí, de modo que es realmente imposible escribir código incorrecto, porque se detecta en tiempo de compilación como un error de tipo.
  • Concurrencia: F# tiene una serie de herramientas y bibliotecas integradas para ayudar con los sistemas de programación cuando ocurre más de una cosa a la vez. La programación asincrónica es directamente compatible, como lo es el paralelismo. F# también tiene un sistema de cola de mensajes y un excelente soporte para el manejo de eventos y programación reactiva. Y debido a que las estructuras de datos son inmutables por defecto, compartir estado y evitar bloqueos es mucho más fácil.
  • Completo. Aunque F # es un lenguaje funcional de corazón, admite otros estilos que no son 100% puros, lo que facilita mucho la interacción con el mundo no puro de sitios web, bases de datos, otras aplicaciones, etc. En particular, F# está diseñado como un lenguaje híbrido funcional / OO, por lo que puede hacer casi todo lo que C# puede hacer también. Por supuesto, F# se integra sin problemas con el ecosistema .NET, que le da acceso a todas las herramientas y bibliotecas .NET de terceros. Finalmente, es parte de Visual Studio, lo que significa que obtiene un buen editor con soporte IntelliSense, un depurador y muchos complementos para pruebas unitarias, control de código fuente y otras tareas de desarrollo.


Aquí hay una descripción general muy rápida sobre cómo leer el código F# para los recién llegados que no estén familiarizados con la sintaxis. La sintaxis F# es muy clara y directa cuando te acostumbras. En muchos sentidos, es más simple que la sintaxis C#, con menos palabras clave y casos especiales.

El siguiente código de ejemplo es un script sencillo de F # que muestra la mayoría de los conceptos que necesita de forma regular.

// single line comments use a double slash
(* multi line comments use (* . . . *) pair -end of multi line comment- *)

// ======== "Variables" (but not really) ==========
// The "let" keyword defines an (immutable) value
let myInt = 5
let myFloat = 3.14
let myString = "hello" //note that no types needed

// ======== Lists ============
let twoToFive = [2;3;4;5]        // Square brackets create a list with
                                 // semicolon delimiters.
let oneToFive = 1 :: twoToFive   // :: creates list with new 1st element
// The result is [1;2;3;4;5]
let zeroToFive = [0;1] @ twoToFive   // @ concats two lists

// IMPORTANT: commas are never used as delimiters, only semicolons!

// ======== Functions ========
// The "let" keyword also defines a named function.
let square x = x * x          // Note that no parens are used.
square 3                      // Now run the function. Again, no parens.

let add x y = x + y           // don't use add (x,y)! It means something
                              // completely different.
add 2 3                       // Now run the function.

// to define a multiline function, just use indents. No semicolons needed.
let evens list =
   let isEven x = x%2 = 0     // Define "isEven" as an inner ("nested") function
   List.filter isEven list    // List.filter is a library function
                              // with two parameters: a boolean function
                              // and a list to work on

evens oneToFive               // Now run the function

// You can use parens to clarify precedence. In this example,
// do "map" first, with two args, then do "sum" on the result.
// Without the parens, "List.map" would be passed as an arg to List.sum
let sumOfSquaresTo100 =
   List.sum ( List.map square [1..100] )

// You can pipe the output of one operation to the next using "|>"
// Here is the same sumOfSquares function written using pipes
let sumOfSquaresTo100piped =
   [1..100] |> List.map square |> List.sum  // "square" was defined earlier

// you can define lambdas (anonymous functions) using the "fun" keyword
let sumOfSquaresTo100withFun =
   [1..100] |> List.map (fun x->x*x) |> List.sum

// In F# returns are implicit -- no "return" needed. A function always
// returns the value of the last expression used.

// ======== Pattern Matching ========
// Match..with.. is a supercharged case/switch statement.
let simplePatternMatch =
   let x = "a"
   match x with
    | "a" -> printfn "x is a"
    | "b" -> printfn "x is b"
    | _ -> printfn "x is something else"   // underscore matches anything

// Some(..) and None are roughly analogous to Nullable wrappers
let validValue = Some(99)
let invalidValue = None

// In this example, match..with matches the "Some" and the "None",
// and also unpacks the value in the "Some" at the same time.
let optionPatternMatch input =
   match input with
    | Some i -> printfn "input is an int=%d" i
    | None -> printfn "input is missing"

optionPatternMatch validValue
optionPatternMatch invalidValue

// ========= Complex Data Types =========

// Tuple types are pairs, triples, etc. Tuples use commas.
let twoTuple = 1,2
let threeTuple = "a",2,true

// Record types have named fields. Semicolons are separators.
type Person = {First:string; Last:string}
let person1 = {First="john"; Last="Doe"}

// Union types have choices. Vertical bars are separators.
type Temp =
| DegreesC of float
| DegreesF of float
let temp = DegreesF 98.6

// Types can be combined recursively in complex ways.
// E.g. here is a union type that contains a list of the same type:
type Employee =
  | Worker of Person
  | Manager of Employee list
let jdoe = {First="John";Last="Doe"}
let worker = Worker jdoe

// ========= Printing =========
// The printf/printfn functions are similar to the
// Console.Write/WriteLine functions in C#.
printfn "Printing an int %i, a float %f, a bool %b" 1 2.0 true
printfn "A string %s, and something generic %A" "hello" [1;2;3;4]

// all complex types have pretty printing built in
printfn "twoTuple=%A,\nPerson=%A,\nTemp=%A,\nEmployee=%A"
         twoTuple person1 temp worker

// There are also sprintf/sprintfn functions for formatting data
// into a string, similar to String.Format.


Dejo link:




martes, 29 de noviembre de 2016

Comparando Scala con F#



Como me gustan las comparaciones, son geniales para peliar con la gente.

En este caso 2 titanes Scala vs F#. Creo que esta comparación tendría mayor sentido si siguieran desarrollando scala.net. Pero creo que este proyecto quedo a la deriva.

Scala corre en javascript, nativo y en java. Y F# en .net y javascript.

Scala fue influido por Java, Ruby y Haskell (entre otros, la lista es muy grande) y  F# es hijo de ML fusionado con todo el poder de .net.

Sin más para agregar les dejo el articulo: http://mikhail.io/2016/08/comparing-scala-to-fsharp/

Que piensan cual es mejor??


miércoles, 26 de octubre de 2016

De F# a Javascript con Fable



Un lector del blog se le ocurrió la genial idea de compartir el link de Fable en un post de ELM. Y estuve leyendo y me intereso bastante.

A todo el mundo al parecer le interesa compilar lenguajes a javascript, y claro, si se esta volviendo muy famoso y omnipresente. Y F# no quiere ser menos, tomando la idea de ELM nace Fable que es un compilador de F# a html y javascript.



Dejo un video:



Dejo link: https://fable.io/

lunes, 8 de febrero de 2016

Lenguajes de programación más solicitados y mejor pagados



Bueno ya publique esto cientos de veces, pero es bueno recordar las implicancias que esta tomando la programación funcional y si no me creen vean este post, sobre todo la parte que indica:

A pesar de su poca frecuencia, los lenguajes mejor pagados son: 

1.-Lisp 

2.-F# 

3.-Haskell 

4.-Scala 

5.-Clojure 

6.-Erlang 

7.-Lua 

Dejo link: http://www.taringa.net/post/info/19148330/Lenguajes-de-programacion-mas-solicitados-y-mejor-pagados.html




lunes, 21 de diciembre de 2015

Cosas que se pueden hacer en F# y no en C#

Estuve viendo este video y me resulto muy entretenido, como el titulo indica ataca las diferencias entre estos dos lenguajes: