Translate

Mostrando las entradas con la etiqueta ML. Mostrar todas las entradas
Mostrando las entradas con la etiqueta ML. Mostrar todas las entradas

martes, 28 de julio de 2020

lunes, 1 de junio de 2020

Breve historia de Haskell


Había una vez un matemático llamado Alonzo Church en la Universidad de Princeton. Church era el supervisor de doctorado de Alan Turing. Church ideó un modelo matemático de funciones llamado cálculo lambda. 

El cálculo lambda captura la esencia de la computación. Implica abstracción de funciones (como definir funciones en Haskell) y aplicaciones (como llamar a funciones en Haskell).

A Uno de los primeros lenguajes de programación de alto nivel fue LISP (que significa procesamiento de lista). LISP adoptó un estilo funcional. Permitía que las funciones del usuario fueran definidas y pasadas como valores. 

Durante la década de 1980, muchos investigadores inventaron y ampliaron varios lenguajes de programación funcionales. Los lenguajes como ML, Hope y Miranda. Sin embargo, la investigación estaba fragmentada en varios lenguajes, y muchos de ellos no eran de "código abierto". Entonces, un grupo de académicos formó un comité para diseñar e implementar un nuevo lenguaje, que se utilizaría como vehículo para la investigación, así como para la enseñanza de la programación funcional.

Después de varios años de trabajo y argumentos, el comité publicó el primer Informe del lenguaje Haskell en 1990. Este fue un hito importante: al fin hubo un lenguaje funcional común en torno al cual la comunidad de investigación podía unirse.

El lenguaje ha crecido en popularidad desde entonces, a pesar del objetivo declarado de evitar el éxito a toda costa. Hay varias implementaciones disponibles gratuitamente. El más utilizado es el Glasgow Haskell Compiler, que tiene un intérprete (ghci) y un compilador (ghc). Estos forman parte integral de la plataforma Haskell. Mucha gente contribuyó a este ecosistema de software. 


Esta historia puede estar mejor contada en este video: 


Erlang en el panorama de la programación funcional.

Erlang es pragmático. Erlang es funcional, pero permite algunos efectos secundarios. Por ejemplo, la forma en que se maneja la comunicación en Erlang es como un efecto secundario. Pero Erlang evita algunos tipos de efectos secundarios. No mantiene estado, tiene lo que se llama asignación única estática. Entonces, aunque el lenguaje en sí es relativamente libre, hay herramientas que ayudan a garantizar la seguridad de los programas que escribimos. Así que hay un buen equilibrio pragmático. 

Si nos fijamos en el panorama del lenguaje de programación funcional, hay bastantes lenguajes que se denominan funcionales. Muchos lenguajes son lo que se llama fuertemente tipado. Lo que queremos decir con tipado fuerte es que cualquier error de tipo que sucede en el lenguaje, lo obtendremos en el momento de la compilación. No se obtienen errores de tipo de tiempo de ejecución. En este grupo tenemos lenguajes como Haskell y Miranda, que tienen lo que se denomina evaluación perezosa.

Lo que eso significa es que la evaluación de las expresiones está impulsada por la demanda. Entonces, en lugar de la evaluación tradicional, que se llama evaluación estricta, donde los argumentos de las funciones se evalúan a medida que se pasan a la función, antes de evaluar el cuerpo de la función. En Haskell y Miranda, los argumentos solo se evalúan cuando la evaluación del cuerpo lo requiere. Por lo tanto, es muy posible que un argumento no se evalúe en absoluto. O es posible que un compuesto, una estructura de datos, solo se evalúe parcialmente. Y esto permite tipos de estructuras de datos infinitos. 

A la vez Haskell y Miranda son completamente puros. No tienen ningún efecto secundario en absoluto. Y eso se debe a que los efectos secundarios y la evaluación perezosa encajan muy mal. La pereza te obliga a ser puro. Esto se debe a que no sabe cuándo se evaluarán partes particulares de una expresión. Entonces, no sabes cuándo ocurriría ese efecto secundario, si estuviera allí. Por otro lado, lenguajes como ML y OCaml y F# tienen una evaluación estricta. Y tienen algunas impurezas. Diferentes lenguajes tienen diferentes equilibrios de impureza, así como Erlang tiene efectos secundarios, tiene impureza en sus primitivas de comunicación. 

Los demás, ML, OCaml, etc., la familia ML son estrictos. Pero estos lenguajes están fuertemente tipados. En el otro extremo del espectro, hay lenguajes débilmente tipados de la familia LISP. Y estos son inherentemente no escritos, si lo desea. Porque construido en el corazón de ellos, tienen una función de evaluación. Entonces puede construir datos y luego evaluar esos datos. Por lo tanto, no hay forma de que sepa de antemano qué tipo de datos tendrá la construcción cuando se evalúen. LISP tiene una larga historia. LISP se inventó por primera vez hace más de 50 años. Y los descendientes de LISP como Common Lisp y Scheme y Racket se usan ampliamente en la actualidad. Pero el núcleo de esos lenguajes es el uso sofisticado de macros y el uso de eval para hacer que estos lenguajes sean muy reflexivos. Pero eso difiere del tipo de cosas que se hacen en Erlang. 

Si para ser un lenguaje de programación funcional, todo lo que necesita es tener una lambda que le permita definir funciones anónimas, entonces tenemos una gran clase de lenguajes de programación funcional. Debido a que Java, JavaScript, Ruby, C ++, casi todos los lenguajes en los que se puede imaginar están obteniendo un lambda, permiten la facilidad de tener funciones anónimas simplemente porque han demostrado ser muy útiles en paradigmas de programación funcional como MapReduce, etc. Pero no se puede considerara estos últimos lenguajes como funcionales. 

jueves, 2 de abril de 2020

Un poco de historia de Haskell

Los orígenes teóricos del modelo funcional se remontan a los años 30 en los cuales Church propuso un nuevo modelo de estudio de la computabilidad mediante el cálculo lambda. Este modelo permitía
trabajar con funciones como ciudadanos de primera clase. En esa misma época, Shönfinkel y Curry
construían los fundamentos de la lógica combinatoria que tendrá gran importancia para la implementación de los lenguajes funcionales.

Hacia 1950, John McCarthy diseñó el lenguaje LISP (List Processing) que utilizaba las listas como
tipo básico y admitía funciones de orden superior. Sin embargo, para que el lenguaje fuese práctico, fue necesario incluir características propias de los lenguajes imperativos como la asignación destructiva y los efectos laterales que lo alejaron del paradigma funcional. Actualmente ha surgido una nueva corriente defensora de las características funcionales del lenguaje encabezada por el dialecto Scheme, que aunque no es puramente funcional, se acerca a la definición original de
McCarthy.

En 1964, Peter Landin diseñó la máquina abstracta SECD para mecanizar la evaluación de expresiones, definió un subconjunto no trivial de Algol-60 mediante el cálculo lambda e introdujo la familia de lenguajes ISWIM (If You See What I Mean) con innovaciones sintácticas (operadores
infijos y espaciado) y semánticas importantes.

En 1978 J. Backus (uno de los diseñadores de FORTRAN y ALGOL) consiguió que la comunidad informática prestara mayor atención a la programación funcional con su artículo “Can Programming
be liberated from the Von Neumann style?” en el que criticaba las bases de la programación imperativa tradicional mostrando las ventajas del modelo funcional. Además Backus diseñó el lenguaje funcional FP (Functional Programming) con la filosofía de definir nuevas funciones combinando otras funciones.

A mediados de los 70, Gordon trabajaba en un sistema generador de demostraciones denominado
LCF que incluía el lenguaje de programación ML (Metalenguaje). Aunque el sistema LCF era interesante, se observó que el lenguaje ML podía utilizarse como un lenguaje de propósito general eficiente. ML optaba por una solución de compromiso entre el modelo funcional y el imperativo ya que, aunque contiene asignaciones destructivas y Entrada/Salida con efectos laterales, fomenta un estilo de programación claramente funcional. Esa solución permite que los sistemas ML compitan en eficiencia con los lenguajes imperativos.

A mediados de los ochenta se realizó un esfuerzo de estandarización que culminó con la definición de
SML (Stándar ML). Este lenguaje es fuertemente tipado con resolución estática de tipos, definición de funciones polimórficas y tipos abstractos. Actualmente, los sistemas en SML compiten en eficiencia con los sistemas en otros lenguajes imperativos.

A comienzos de los ochenta surgieron una gran cantidad de lenguajes funcionales debido
a los avances en las técnicas de implementación. Entre éstos, se podrían destacar Hope, LML, Orwell, Erlang, FEL, Alfl, etc. Esta gran cantidad de lenguajes perjudicaba el desarrollo del paradigma funcional. En septiembre de 1987, se celebró la conferencia FPCA en la que se decidió formar un comité internacional que diseñase un nuevo lenguaje puramente funcional de propósito general denominado Haskell.

Con el lenguaje Haskell se pretendía unificar las características más importantes de los lenguajes
funcionales. como las funciones de orden superior, evaluación perezosa, inferencia estática de tipos,
tipos de datos definidos por el usuario, encaje de patrones y listas por comprensión. Al diseñar el
lenguaje se observó que no existía un tratamiento sistemático de la sobrecarga con lo cual se construyó una nueva solución conocida como las clases de tipos. El lenguaje incorporaba, además, Entrada/Salida puramente funcional y definición de arrays por
comprensión.

Durante casi 10 años aparecieron varias versiones del lenguaje Haskell, hasta que en 1998 se decidió
proporcionar una versión estable del lenguaje, que se denominó Haskell98, a la vez que se continuaba
la investigación de nuevas características y nuevas extensiones al lenguaje.

Dejo link: https://es.wikipedia.org/wiki/Haskell

domingo, 22 de marzo de 2020

HTML + javascript + Haskell = ELM, parte 7



Seguimos con el post anterior.

Agregaremos un par de funciones para contar la cantidad de interacciones con el mouse. En lenguajes funcionales como Elm, debes aprender trucos para manejar el estado. Hemos visto cómo las señales pueden ayudar a acceder a cosas como la posición del mouse que cambia con el tiempo y cómo usamos la recursividad para procesar listas. Gestionamos el estado por la forma en que estructuramos nuestras funciones. Las funciones de folds, que quizás conozcas de Lisp o Haskell, son un buen ejemplo. Toman una función de dos argumentos, un valor inicial y una lista. Aquí hay un ejemplo de foldl en Elm:

> foldl (+)  0  [1, 2, 3]
6 : number

Esto es lo que sucede en cada paso:

  • fold (+) 0 [1, 2, 3]. fold toma el valor inicial de la lista, 1, y el acumulador, 0, y los suma, devolviendo 1, y usa ese número, con el resto de la lista, llamando a fold nuevamente.
  • fold (+) 1 [2, 3]. Elm toma el valor más a la izquierda de la lista, 2, y el acumulador, 1, y los pasa a la función (+), devolviendo 3.
  • fold (+) 3 [3]. Llamamos (+) con el acumulador 3 y el elemento de lista más a la izquierda de 3, devolviendo 6, y hemos terminado.

Ahora, creamos una señal con foldp. Esa señal agrega el acumulador, llamado presses, al valor x de la señal de Keyboard.arrows. Luego podemos asignar ese valor a la función show. Ahora, cuando ejecute la aplicación, obtendrá un total de presses. 

Usemos el mismo principio general para contar los movimientos del mouse. Signal.map aplica una señal a una función. Signal.foldp se pliega sobre una señal:

import Mouse
import Graphics.Element exposing (show)
count signal = Signal.foldp (\_ n -> n + 1) 0 signal
main = Signal.map show (count Mouse.position)

La función de conteo toma una señal y agrega una cada vez que la señal cambia. foldp funciona igual que foldl, pero en lugar de doblar una lista desde la izquierda, foldp se pliega a través del tiempo. Nuestra función foldp toma una función anónima que agrega uno a un valor, comienza con un valor inicial de 0 y proporciona una señal. Nuestra nueva señal tendrá valores que comienzan con 0 que aumentan cada vez que se actualiza la señal. Podemos cambiar fácilmente el programa para contar los clics del mouse:

import Mouse
import Graphics.Element exposing (show)
main = Signal.map show (count Mouse.clicks)
count signal = Signal.foldp (\_ n -> n + 1) 0 signal

En este caso, la función de conteo cuenta el número de actualizaciones de señal, que son clics del mouse. Puede comenzar a ver cómo podemos escribir código que respete las reglas de la programación funcional, pero que sea reactivo y fácil de entender.

Veamos cómo funcionarían las señales del teclado:

import Graphics.Element exposing (show)
import Keyboard
main = Signal.map show Keyboard.arrows

Map actualiza el texto cuando cambia la señal, por lo que obtenemos un programa limpio que nos dice el estado de las teclas de flecha, en una forma que podemos usar fácilmente. Como podemos componer con funciones, podemos ser más sofisticados.



sábado, 21 de marzo de 2020

HTML + javascript + Haskell = ELM, parte 6

Seguimos con el post anterior.

Elm fue construido desde cero para manejar los aspectos más difíciles del desarrollo de la interfaz de usuario. Se puede utilizar para crear una aplicación comercial con controles de interfaz de usuario o un juego, debe poder reaccionar ante los eventos. De hecho, todo lo que haces es una reacción a algún evento. El programa típico de JavaScript se basa en enviar eventos a través de funciones de callbacks, lo que hace que los programas sean mucho más receptivos pero a un costo. Son demasiado difíciles de leer. Aquí hay un ejemplo típico usando la biblioteca JQuery con JavaScript que le permite tomar la posición del mouse:

$(document).ready(function () {
       var position = {'x': 0, 'y': 0};
      $(document).bind('mousemove', function(event) {
                   position = {'x': event.pageX, 'y': event.pageY};
       });
       setInterval(function () {
      // custom position code
      }, seconds * 1000);
});

Comprender ese código requiere un poco de experiencia. Cuando se carga la página, recibimos una devolución de llamada lista. En ese momento, vinculamos el evento mousemove a una función que establece una variable de posición. Luego, a intervalos específicos, tenemos otra función de callback que utiliza la posición. Tenga en cuenta que nuestro código vincula funciones anónimas a eventos. Dicho de otra manera, estamos poniendo JavaScript a cargo de la organización del código. A esta estrategia de programación de adentro hacia afuera la llamamos inversión de control.

Para una característica tan trivial, ese código es demasiado complejo, pero es una compensación. Obtenemos una mejor capacidad de respuesta ya que este programa cambiará la posición del mouse cada vez que el usuario mueva el mouse. Cambiamos la simplicidad. El problema es que realmente necesitamos ambos.

import Graphics.Element exposing (..)
import Mouse
main = Signal.map show Mouse.position

La directiva de exposición nos permite mostrar sin especificar el módulo. Luego, haga clic en el botón de compilación. Verás una salida similar a esta:

(29, 162)

Eso es mucho más simple. Importamos los módulos Graphics.Element y Mouse, y luego declaramos la función principal.

Conceptualmente, la señal Mouse.position representa los valores de xey que varían con el tiempo. Signal.map aplica una señal a una sola función.

En el código anterior, la señal Mouse.position representa una tupla que contiene la posición del mouse a lo largo del tiempo. Nuestra función es show, que se convierte en texto.

Mouse.position se "disparará" cada vez que el mouse se mueva, y Signal.map volverá a evaluar show con la nueva posición del mouse. Curiosamente, el resultado es una nueva señal!

Mirando la parte inferior de la ventana, puede ver que la principal es en realidad una señal, una que mostramos en la pantalla. Eso significa que Elm actualizará la ventana cada vez que se mueva la posición del mouse.

No hay call back ni inversión de control. Simplemente usamos una señal, la convertimos a texto y mapeamos el valor actual cuando la señal cambia. 

domingo, 15 de marzo de 2020

HTML + javascript + Haskell = ELM, parte 5

Seguimos con el post anterior.

Elm incluye Pattern Matching, Puede usarlo para simplificar algunas definiciones de funciones:

> first (head::tail) = head
<function> : List a -> a
> first [1, 2, 3]
1 : number

Se deberá cubrir todos los casos o se puede tener este error:

> first []
Error: Runtime error in module Repl (on line 23, column 22 to 26):
Non-exhaustive pattern match in case-expression.
Make sure your patterns cover every case!

Como head :: tail no coincide [], Elm no sabe qué hacer con esta expresión. Usar una coincidencia de patrón no exhaustiva es una de las pocas formas en que puede bloquear un lenguaje de la familia ML y es totalmente evitable.

Elm es un lenguaje curry como Haskell :

> add x y = x + y
<function> : number -> number -> number

Observe el tipo de datos de la función. Es posible que haya esperado una función que tome dos argumentos de tipo número y devuelva un tipo de número. Así es como funciona el curry. Elm puede aplicar parcialmente add, lo que significa que puede completar uno de los dos números, así:

> inc = (add 1)
<function> : number -> number

Acabamos de crear una nueva función parcialmente aplicada llamada inc. Esa nueva función aplica uno de los argumentos para agregar. Completamos x, pero no y, así que Elm básicamente está haciendo esto:

addX y = 1 + y

Curry significa cambiar las funciones de múltiples argumentos a una cadena de funciones que cada una toma un solo argumento. Ahora, podemos manejar el curry nosotros mismos. Recuerde, las funciones currificadas no pueden tomar más de un argumento a la vez:

> add x y = x + y
<function> : number -> number -> number
> add 2 1
3 : number
> (add 2) 1
3 : number

Además de curring, puedes usar funciones parcialmente aplicadas para crear algunos algoritmos geniales. 

Elm infiere que vas a hacer aritmética con números. Elm usa el número de clase de tipo porque esa es la clase de tipo que admite el operador +. Sin embargo, no está limitado a enteros:

> add 1 2
3 : number
> add 1.0 2
3 : Float
> add 1.0 2.3
3.3 : Float

Y esto funciona porque Elm es polimórfico. Calcula el tipo más general que funcionará, en función de su uso de operadores. De hecho, puede ver el mismo comportamiento con el operador ++:

> concat x y = x ++ y
<function> : appendable -> appendable -> appendable

Elm asume que la función usa dos elementos anexables, como este:

> concat ["a", "b"] ["c", "d"]
["a","b","c","d"] : [String]
> concat "ab" "cd"
"abcd" : String

Eso es polimorfismo. Como es de esperar, también puede usar polimorfismo con puntos. Digamos que tengo un punto y quiero calcular la distancia al eje x. Eso es fácil de hacer:

> somePoint = {x=5, y=4}
{ x = 5, y = 4 } : {x : number, y : number'}
> xDist point = abs point.x
<function> : {a | x : number} -> number
> xDist somePoint
5 : number

La inferencia de tipos de Elm infiere que x e y son números dentro de un registro. Ahora, puedo pasarlo en cualquier punto:

> twoD = {x=5, y=4}
{ x = 5, y = 4 } : {x : number, y : number'}
> threeD = {x=5, y=4, z=3}
{ x = 5, y = 4, z = 3 } : {x : number, y : number', z : number''}
> xDist twoD
5 : number
> xDist threeD
5 : number

Alternativamente, podría usar la coincidencia de patrones, así:

> xDist {x} = abs x
<function> : { a | x : number } -> number
> xDist threeD
5 : number

Con  Pattern Matching seleccionar el campo x, y el resto del ejemplo funciona de la misma manera. El punto es que los registros también son completamente polimórficos. A Elm no le importa que los registros que utilizamos sean del mismo tipo. Solo necesita el registro para tener un campo x. Estás viendo el poder de un sistema de tipos que hará todo lo posible para detectar problemas reales, pero que se saldrá del camino cuando no haya ninguno.




miércoles, 4 de marzo de 2020

HTML + javascript + Haskell = ELM



Supongamos que tenemos que hacer un juego en Html, css y javascript. Ante esta idea, viene otra muy rápidamente relacionada con el suicidio.

Por suerte existe ELM, que es un lenguaje inspirado en Haskell el cual esta orientado a sistemas reactivos y compila a HTML y javascript.

Antes de comenzar debemos instalar ELM. ELM cuenta con 2 herramientas, una es el RELP y otra es le server. Por ahora vamos a utilizar el RELP.

Para instalar el RELP, vamos a : https://guide.elm-lang.org/install/elm.html
O podemos utilizar el try : https://elm-lang.org/try

Instalado el RELP, vamos a ver expresiones en ELM y literales : 
 > 4
4 : number

> "String"
"String" : String

> 5 < 4
False : Bool

Todo retorna un valor y ese valor tiene un tipo. ELM es de tipado estático y su tipado es muy poderoso pero algo quisquilloso :

> [1, "2"]
[1 of 1] Compiling Repl
 ( repl-temp-000.elm )
The 2nd element of this list is an unexpected type of value.
3|
 [1, "2"]
^^^
...
> 4 + "4"
[1 of 1] Compiling Repl
...
( repl-temp-000.elm )
As I infer the type of values flowing through your program, I see a conflict
between these two types: number String
> "4" ++ "4"
"44" : String
> 4 ++ 4
[1 of 1] Compiling Repl
...
Expected Type: appendable
...
> [1, 2] ++ [3, 4]
[1,2,3,4] : [number]
( repl-temp-000.elm ) 

Por lo visto, ELM es de tipado fuerte y estático.  ELM esta influenciado por el sistema de tipos de Haskell y ML. Su sistema de tipo contiene type classes. Esto se puede ver como las interfaces de Java. Es decir, un tipo implementa estas interfaces y todas las funciones que trabajan con este data type, puede ser utilizados con el tipo.

Por ejemplo tanto las listas como los Strings son appendable por lo tanto toda función que necesitan un appendable pueden ser utilizadas con listas o String por ejemplo ++.

A la vez ELM infiere el tipo, no es necesario indicar le tipo dado que este es inferido por el compilador : 

> a = [1, 2, 3]
[1,2,3] : [number]

A la vez cuenta con un sistema de tipos polimorfico, lo que significa que puede tratar los tipos que heredan de la misma type class de la misma manera. Verá que Elm aprovecha al máximo su herencia de ML y Haskell para construir uno de los mejores sistemas de tipos del mundo.

> a[1] = 2
[1 of 1] Compiling Repl ( repl-temp-000.elm )
> a[1] = 2
<function> : List number -> number'


Elm es un lenguaje de tipado estático, y muy estricto, aunque en REPL, puede redefinir valores primitivos por conveniencia. Elm es como Elixir a este aspecto. : List number -> number'

Creo que por este post estamos, continuará ...

Dejo link :  https://elm-lang.org/


lunes, 2 de abril de 2018

Ur, un lenguaje funcional puro

Ur es un lenguaje de programación similar a ML y Haskell, pero presenta un sistema de tipos significativamente más rico. Ur es funcional puro, estáticamente tipado y estricto. Ur soporta metaprogramación basada en el sitema de row types.

Ur/Web es Ur más una biblioteca estándar especial y reglas asociadas para el análisis sintáctico y la optimización web. Ur/Web admite la construcción de aplicaciones web dinámicas respaldadas por bases de datos SQL. Ur/Web utiliza el tipado estatioco de tal manera que las paginas generadas no pueden :

  • Sufrir cualquier tipo de ataque de inyección de código
  • Retornar HTML no válido
  • Contiener enlaces muertos o invalidos dentro de la aplicación
  • Tener desajustes entre formularios HTML y los campos esperados por sus controladores
  • Incluir el código del lado del cliente que hace suposiciones incorrectas sobre los servicios de estilo "AJAX" que proporciona el servidor web remoto
  • Intentar consultas SQL no válidas
  • Usar referencias o bases de datos impropias en la comunicación con bases de datos SQL o entre navegadores y servidores web


Este tipo de seguridad es solo la base de la metodología Ur/Web. También es posible usar la metaprogramación para construir piezas de aplicación significativas mediante el análisis de la estructura de tipos. Por ejemplo, la demostración incluye un functor estilo ML para construir una interfaz de administración para una tabla SQL arbitraria. El sistema de tipo garantiza que la sub-aplicación de interfaz siempre estará libre de los errores mencionados anteriormente, sin importar qué descripción de tabla bien tipada.

El compilador de Ur/Web también produce código de objeto muy eficiente que no utiliza la recolección de elementos no utilizados. Estos programas compilados a menudo serán incluso más eficientes de lo que la mayoría de los programadores se tomarían la molestia de escribir en C. Por ejemplo, el servidor web independiente generado para la demostración utiliza menos memoria RAM que el shell bash. El compilador también genera versiones JavaScript del código del lado del cliente, sin necesidad de escribir esas partes de las aplicaciones en un lenguaje diferente.

Y como esto furra poco la implementación de todo esto es de código abierto.

Dejo link: http://www.impredicative.com/ur/

miércoles, 7 de septiembre de 2016

Objective Categorical Abstract Machine Language o OCaml para los amigos


Objective CAML, también conocido Ocaml, el nombre proviene de las siglas en inglés Objective Categorical Abstract Machine Language. Es un hijo de ML, desarrollado y distribuido por el INRIA en Francia. Ocaml admite los paradigmas de programación imperativa, programación funcional y programación orientada a objetos.

Es un lenguaje que reúne ML con Objetos, que no se si es lo mejor. Pero es un intento de introducir objetos a un lenguaje funcional.

Es de tipado estático y por lo tanto tiene chequeo por tipos. Que más tenemos? objetos, polimorfismo, pattern matching, garbage collection, generic, etc.

Veamos un hola mundo:

 > print_endline "Hello World !" ;;
 Hello World !
 val () : unit = <fun>

  (* Listas genéricas *)
 
  (* Longitud de una lista *)
  let rec long  = function
    |[] -> 0
    |x::xs -> 1 + long xs;;

  (* Ordenamiento por inserción *)
  (* dada una relación de orden *)
  let rec ordenar = function
    |[] -> []
    |x::xs -> insertar x (ordenar xs)
  and insertar e = function
    |[] -> [e]
    |x::xs -> if x > e
              then e::x::xs
              else x::(insertar e xs);;



Dejo link:
https://ocaml.org/

viernes, 13 de febrero de 2015

Cual es el mejor lenguaje para a prender programación funcional?


Me encontré con esta pregunta en internet y me resulta muy interesante...

Yo pienso en scala, haskell o sml . También es buena idea utilizar un lenguaje de tipado débil como Lisp o erlang...

Pero admito que me gusta aprender lenguajes, tal vez el más completo es Haskell. Pero esta es una opinión personal.

Seria muy interesante que opinen, les dejo el link:
http://www.slant.co/topics/485/~what-are-the-best-languages-for-learning-functional-programming

jueves, 16 de octubre de 2014

Standard ML

Estoy haciendo el curso de corsera sobre lenguajes de programación y en este curso se estudia Standard ML y madre mía ,que lenguaje!!! Y obvio despertó mi curiosidad, veamos que nos dice la wikipedia sobre SML: 

"El lenguaje de programación Standard ML o SML es un lenguaje descendiente del lenguaje ML que nació como el Meta Lenguaje del sistema LCF. A diferencia de muchos otros lenguajes de programación, SML tiene una especificación formal, como semántica operacional publicada en el libro The Definition of Standard ML."

Yo ya hable de SML en otro post pero mi inconstancia, no dejo que profundice. Seguramente estas pensando que me puede aportar este lenguaje? Que lo hace especial?

Como primer punto es un lenguaje funcional y es de tipado estático, con genéricos. A la vez el compilador infiere los tipos por lo que tiene el sistema de tipos más simple y mejor diseñado que he usado, y si no mira:

- val i = 2
val i = 2 : int
- val miLista = [1,1,3,4,5]
val miLista = [1,1,3,4,5] : int list
- val otraLista = [miLista, [1,2,8]]
val otraLista = [[1,1,3,4,5],[1,2,8]] : int list list
- val unString="unString"
val unString = "unString" : string

Si ven otraLista es de tipo list y es genérica. Y este genérico es de tipo lista de enteros, en java sería así:

List<List<Integer>>

Al ser un lenguaje funcional las funciones son lo más importante, y se definen de la siguiente manera:

- fun sumar (a:int, b:int):int = a + b
val sumar = fn : int * int -> int
- sumar (4, 5)
val it = 9 : int

Como ven la función sumar es de tipo int * int -> int , lo que significa que tiene dos parámetros enteros y devuelve un entero. 

Otro tipo interesante son las tuplas, son colecciones de elementos de un mismo tipo que se pueden acceder por un indice, similar a los arreglos:

- fun sumarTupla(tupla: int * int) : int = #1 tupla + #2 tupla
val sumarTupla = fn : int * int -> int
- sumarTupla((1,2))
val it = 3 : int

SML es un lenguaje que tiene un sistema de tipos muy simple, voy a seguir postiando cosas interesantes sobre el lenguaje. 



domingo, 13 de abril de 2014

Pattern matching


Pattern Matching nace del paradigma funcional aunque hoy en día lenguaje multiparadigma lo implementan como Scala o Kotlin. Pattern Matching permite definir funciones por medio de macheo de parámetros y resultados. Veamos un ejemplo en Haskell de definición de factorial:

 factorial 0 = 1
 factorial n = n * factorial (n - 1)

Para ver la diferencia entre la forma de resolver el problema sin Pattern Matching, voy a resolver lo mismo en C++

 int factorial(int n) {
       if (n == 0) {
              return 1;
       } else {
             return n * factorial(n-1);
       }
 }

Si comparamos nos ahorramos 5 lineas; pero el tema no es solo escribir menos código. Además debemos pensar: ¿Cuál les parece más legible? ¿Cuál es más simple?

Muchos lenguajes implementan Pattern Matching, al venir del paradigma funcional normalmente los lenguajes funcionales como Erlang lo implementan; vamos a hacer la función de factorial en Erlang.

 fac(0) -> 1;
 fac(N) when N > 0, is_integer(N) -> N * fac(N-1).

Se puede ver que en este caso se indica que debe ser positivo el número; si se ingresa un valor negativo lanza un error. Ojo estas restricciones también la podíamos hacer en Haskell.

 Factorial con ML se vería de la siguiente manera:

 fun fac 0 = 1
      | fac n = n * fac (n - 1)

 Otros lenguajes multiparadigma nos permiten jugar con Patter Matching como Scala:

 def fact(n: Int): Int = n match {
     case 0 => 1
     case n => n * fact(n - 1)
   }

En este caso se define fact que devolverá un entero, y que el parámetro n debe coincidir con 0 y devuelve 1 o con cualquier otro valor y devolverá n * fact(n - 1).

 Por ejemplo Kotlin permite hacer Pattern Maching por el tipo de la siguiente manera:

 when (x) {
   is Int -> print(x)
   is List<Int> -> print(x.sum())
   !is Number -> print("No es un número")
   else -> print("No puedo hacer nada")
 }

Para citar otro ejemplo, veamos desarrollar una función que indique el número que se encuentra en una posición indicada por parámetro de la secuencia de Fibonacci, y lo desarrollaremos con F# :

 let rec fib n =
     match n with
     | 0 -> 0
     | 1 -> 1
     | 2 -> 1
     | _ -> fib (n - 1) + fib (n - 2)

 Si lo comparamos con Mathematica:
 fib[0]:=0
 fib[1|2]:=1
 fib[n_]:= fib[n-1] + fib[n-2]

En Mathematica podemos utilizar el | para decir esto o aquello y el _ para indicar cualquier otro valor.

Pattern Matching es una técnica muy simple, pero muy potente. Por ejemplo necesitamos el primer elemento de una lista podemos definirla de la siguiente manera, vamos a implementarlo en Haskell:

primero :: [a] -> a
primero [] = error "¡No puedes utilizar la función primero con una lista vacía!"
primero (x:_) = x

Con (x:_) estamos diciendo que puede llegar una lista por parámetro que está conformada por un elemento y el resto. Implementemos la función cantidadDeElementos que nos indique cuantos elementos tiene una lista:

cantidadDeElementos :: (Num b) => [a] -> b
cantidadDeElementos [] = 0
cantidadDeElementos (_:xs) = 1 + cantidadDeElementos xs

Una desventaja del uso de Pattern Matching es que nuestro código se verá muy afectado ante un cambio en las estructuras. Pero la ventajas son muchísimas, para citar algunas: legibilidad de código, simplicidad, menos lineas de código, etc...

domingo, 9 de marzo de 2014

La historia de los lenguajes de programación

He posteado varias infografias o comparativas de lenguajes pero creo que ninguna es tan completa y fácil de leer como la que adjunto. Y a la vez muestra las personas detrás del lenguaje.

Dejo link:
http://thequickword.wordpress.com/2014/02/16/james-irys-history-of-programming-languages-illustrated-with-pictures-and-large-fonts/

sábado, 19 de octubre de 2013

Conociendo ML


ML es un lenguaje funcional desarrollado por Robin Milner en los años 70, no es un lenguaje muy usado pero esta lleno de conceptos que son usados en otros lenguajes.

Vamos por parte, es un lenguaje Funcional por lo tanto las funciones son ciudadanos de primera clase. Y a la vez hace un uso intensivo de recursividad, veamos un ejemplo:

fun fac (0 : int) : int = 1
  | fac (n : int) : int = n * fac (n - 1)

Como pueden ver en el ejemplo es de tipado estático, es decir tenes que poner expresamente el tipo, el compilador no lo infiere.

También tiene listas y las listas son tipadas:

- [];
val it = [] : 'a list
- [1,2,3,4,5]
= ;
val it = [1,2,3,4,5] : int list
- [2,3,"hola"];
stdIn:7.1-7.13 Error: operator and operand don't agree [literal]
  operator domain: int * int list
  operand:         int * string list
  in expression:
    3 :: "hola" :: nil

El error es porque quiero poner elementos de diferente tipo en la misma lista. 

Como la mayoria de los lenguajes funcionales ven una lista como el ultimo elemento y el resto; lo que permite junto a la recursividad hacer cosas muy interesantes:

fun contar (xs : int list) : int =
      if null xs then 0
      else 1 + contar(tl xs)
;
contar([1,2,3,4,5]);

Aclaro que null es una función que nos indica que la lista es vacía, y el algoritmo hace lo siguiente si la lista es vacía devuelve 0, si no devuelve 1 más la cantidad de el resto de los elementos de la lista. Con la función tl obtenemos el resto de la lista, sin el ultimo elemento, veamos otro ejemplo:

fun sumar (xs : int list) : int =
      if null xs then 0
      else hd xs + sumar(tl xs)
;
sumar([1,2,3,4,5]);

Con la función hd tomamos el ultimo elemento, es decir que lo que estamos diciendo es que la suma de todos los elementos es igual a la suma del ultimo elemento más la suma de los demás elementos.

Prometo otros posts!

Dejo link:
http://en.wikipedia.org/wiki/ML_(programming_language)