Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Haskell
Wiki community
Recent changes
Random page
HaskellWiki
Search
Search
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
Es/Por que Haskell importa
(section)
Page
Discussion
English
Read
Edit
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
View history
General
What links here
Related changes
Special pages
Page information
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
== Qu茅 puede ofrecer Haskell al programador? == Haskell es un lenguaje moderno de prop贸sito general desarrollado para incorporar el conocimiento colectivo de la comunidad de programaci贸n funcional en un lenguaje elegante, poderoso y general. ===Pureza=== A diferencia de otros lenguajes de programaci贸n funcional Haskell es puro. No permite ''ning煤n'' efecto lateral. Este es probablemente la caracter铆stica m谩s importante de Haskell. Ya hemos discutido brevemente los beneficios de la programaci贸n pura, libre de efectos laterales - y no hay mucho m谩s que podamos decir sobre eso. Necesitas experimentarlo tu mismo. ===Pereza=== Otra caracter铆stica de Haskell es que es perezoso (hablando t茅cnicamente, esto es "no-estricto"). Esto significa que no se eval煤a nada hasta tanto deba ser evaluado. Uno puede, por ejemplo, definir una lista infinita de primos sin caer en una recursi贸n infinita. S贸lo los elementos de esta lista que sean realmente usados ser谩n computados. Esto permite algunas soluciones muy elegantes para muchos problemas. Un patr贸n t铆pico de resoluci贸n de un problema ser铆a definir una lista de todas las posibles soluciones y luego filtrar las ilegales. La lista resultante tendr谩 s贸lo soluciones legales. La evaluaci贸n perezosa hace esta operaci贸n muy limpia. Si solo se necesita una soluci贸n, simplemente se puede tomar el primer elemento de la lista resultante - la evaluaci贸n perezosa nos asegurar谩 que nada m谩s es evaluado innecesariamente. ===Tipado fuerte=== M谩s aun Haskell es fuertemente tipado, esto significa lo que dice. Es imposible convertir sin darse cuenta un Double a un Int, o seguir un puntero nulo. Esto tambi茅n lleva a tener menos errores. Puede ser doloroso en los raros casos en que uno necesita convertir un Int a un Double expl铆citamente antes de hacer alguna operaci贸n, pero en la pr谩ctica eso no sucede muy a menudo como para convertirse en una molestia. De hecho, forzar cada conversi贸n expl铆citamente puede ayudar a resaltar problemas en el c贸digo. En otros lenguajes donde estas conversiones son invisibles, los problemas surgen frecuentemente cuando el compilador trata un double como un entero o, aun peor, un entero como un puntero. A diferencia de otros lenguajes fuertemente tipados, en Haskell los tipos son inferidos autom谩ticamente. Esto significa que rara vez tendr谩s que declarar los tipos de tus funciones, excepto como forma de documentaci贸n. Haskell mirar谩 c贸mo usas las variables y se dar谩 cuenta de eso qu茅 tipo deber铆a tener la variable - despu茅s se har谩 un chequeo de tipos de todo para asegurarse que todos los tipos coinciden. Python tiene la noci贸n de "duck typing", que significa "si camina y habla como un pato, entonces es un pato!". Se puede argumentar que Haskell tiene una forma mejor de "duck typing". Si un valor camina y habla como un pato, entonces ser谩 considerado un pato a trav茅s de la inferencia de tipos; pero, a diferencia de Python, el compilador tambi茅n atrapar谩 los errores si despu茅s intenta comportarse como un mono! Tu obtienes los beneficios de tipado fuerte (se capturan errores en tiempo de compilaci贸n, en vez de en tiempo de ejecuci贸n) sin las molestias que acarrea esto en otros lenguajes. M谩s aun, Haskell siempre inferir谩 el tipo m谩s general para una variable. Por lo tanto, si tu escribes una funci贸n de ordenamiento sin una declaraci贸n de tipos, Haskell se asegurar谩 que la funci贸n acepte cualquier valor que pueda ser odenado. Compara esto con c贸mo lo har铆as en alg煤n lenguaje orientado a objetos. Para tener polimorfismo, tendr铆as que usar alguna clase base, y despu茅s declarar tus variables como instancias de subclases de esa clase. Eso significa un mont贸n de trabajo extra y declaraciones rid铆culamente complicadas s贸lo para declarar la existencia de una variable. M谩s aun, tendr铆as que realizar muchas conversiones de tipo a trav茅s de conversiones ("casts") expl铆citos - lo cual no es definitivamente una soluci贸n elegante. Si tu quieres escribir una funci贸n polim贸rfica en estos lenguajes orientados a objetos, probablemente declarar铆as los par谩metros como objetos de una clase base global (como "Object" en Java), que escencialmente permite le permite al programador pasarle cualquier cosa a la funci贸n, aun objetos que l贸gicamente no pueden ser pasados a la funci贸n. El resultado es que la mayor铆a de las funciones que escribes en esos lenguajes no son generales, s贸lo funcionan con un solo tipo de datos. Est谩s tambi茅n corriendo el control de errores de tiempo de compilaci贸n a tiempo de ejecuci贸n. En sistemas grandes donde alguna funcionalidad se usa raramente, estos errores pueden no ser vistos hasta que causan un error fatal en el peor momento posible. Haskell provee una form elegante, concisa y segura de escribir programas. Los programas no se colgar谩n inesperadamente, ni producir谩n basura extra帽a como salida. ===Elegancia=== Otra propiedad de Haskell que es muy importante para el programador, aun cuando no signifique mucho en t茅rminos de estabilidad o performance, es la elegancia. Para decirlo sencillamente: las cosas funcionan como tu te lo imaginas. Para destacar la elegancia de Haskell repasaremos un peque帽o ejemplo. Elejimos QuickSort porque es un algoritmo simple y realmente 煤til. Miraremos dos versiones - una escrita en C++, un lenguaje imperativo, y una escrita en Haskell. Ambas versiones s贸lo usan la funcionalidad disponible para el programador sin importar m贸dulos extras (de otra forma podr铆amos simplemente invocar a la funci贸n "sort" de la biblioteca est谩ndar de cada lenguaje y estar铆amos hechos!). Entonces, vamos a usar las primitivas est谩ndar de secuencias de cada lenguaje (una "lista" en Haskell y un "array" en C++). Ambas versiones deben ser polim贸rficas (lo que es hecho autom谩ticamente por Haskell, y con templates en C++). Ambas versiones deben usar el mismo algoritmo recursivo. Por favor nota que esto ''no'' tiene la intenci贸n de ser una comparaci贸n definitiva entre los lenguajes. S贸lo se quiere mostrar la elegancia de Haskell, la versi贸n C++ s贸lo se incluye a los fines de la comparaci贸n (y podr铆a haber sido codificada de otra manera si usaramos la Standard Template Library, por ejemplo). template <typename T> void qsort (T *result, T *list, int n) { if (n == 0) return; T *smallerList, *largerList; smallerList = new T[n]; largerList = new T[n]; T pivot = list[0]; int numSmaller=0, numLarger=0; for (int i = 1; i < n; i++) if (list[i] < pivot) smallerList[numSmaller++] = list[i]; else largerList[numLarger++] = list[i]; qsort(smallerList,smallerList,numSmaller); qsort(largerList,largerList,numLarger); int pos = 0; for ( int i = 0; i < numSmaller; i++) result[pos++] = smallerList[i]; result[pos++] = pivot; for ( int i = 0; i < numLarger; i++) result[pos++] = largerList[i]; delete [] smallerList; delete [] largerList; }; No explicaremos este c贸digo, s贸lo notemos c煤an complejo y dif铆cil es entenderlo en una mirada, principalmente porque el programador tiene que lidiar con detalles de bajo nivel que no tienen nada que ver con la tarea a resolver. Ahora veamos la versi贸n de QuickSort en Haskell, que luce como sigue: <haskell> qsort [] = [] qsort (x:xs) = qsort less ++ [x] ++ qsort more where less = filter (<x) xs more = filter (>=x) xs </haskell> Desglosemos este c贸digo en detalle, ya que usa mucha sintaxis de Haskell que puedes no conocer. La funci贸n se llama qsort y toma una lista como su par谩metro. Definimos una funci贸n en Haskell as铆: nombrefuncion a b c = expr, donde nombrefuncion es el nombre de la funci贸n, a, b, y c son los par谩metros y expr es la expresi贸n a ser evaluada (usualmente usando los par谩metros). Las funciones se llaman simplemente escribiendo su nombre primero y luego su(s) par谩metro(s). Haskell no usa par茅ntesis para la aplicaci贸n funcional. Las funciones simplemente tienen m谩s precedencia que cualquier otra cosa, entonces "f 5 * 2", por ejemplo, aplicar铆a f a 5 y luego lo multiplicar铆a por 2; si quisieramos que la multiplicaci贸n ocurriera antes de la aplicaci贸n entonces usar铆amos par茅ntesis como en "f (5*2)". Volvamos al QuickSort. primero vemos que tenemos dos definiciones para la funci贸n. Esto se llama ajuste de patrones (pattern matching) y brevemente podemos decir que probar谩 el argumento pasado a la funci贸n con los patrones desde arriba hacia abajo, usando el primero que se ajuste. La primera definici贸n se ajusta a [] que en Haskell es la lista vac铆a (una lista de 1, 2 y 3 es [1,2,3] as铆 que tiene sentido que la lista vac铆a sean s贸lo dos corchetes). As铆 que cuando tratamos de ordenar la lista vac铆a, el resultado ser谩 una lista vac铆a. 驴Suena razonable, no? El segundo patr贸n de definici贸n se ajusta a una lista con al menos un elemento. Lo hace usando (x:xs) como su argumento. El operador "cons" es (:) y simplemente pone un elemento en frente de una lista, as铆 0 : [1,2,3] devuelve [0,1,2,3]. El ajuste de patrones contra (x:xs) se cumple con una lista con cabeza x y cola xs (que puede o no ser la lista vac铆a). En otras palabras, (x:xs) es una lista de al menos un elemento. As铆 que como necesitaremos usar la cabeza de la lista despu茅s, podemos extraerla muy elegantemente mediante el ajuste de patrones. Puedes pensarlo como nombrar el contenido de la lista. Esto se puede hacer para cualquier construcci贸n de datos, no s贸lo una lista. Es posible ajustar patrones con un nombre de variable arbitrario y luego usar la funci贸n head para obtener la cabeza de la lista. Ahora si tenemos una lista no vac铆a, la lista ordenada se produce ordenando todos los elementos menores a x y poni茅ndolos en frente de x, y luego ordenando todos los elementos mayores a x y poni茅ndolos al final. Hacemos esto usando el operador de concatenaci贸n de listas ++. N贸tese que x no es una lista as铆 que el operador ++ no funcionar谩 sobre ella, por lo que hacemos una lista unitaria al ponerla entre corchetes. As铆, la funci贸n se lee "Para ordenar la lista, ubica la cabeza entre la lista ordenada de todos los elementos menores a ella y la lista ordenada de todos los elementos mayores a ella". Esta frase podr铆a bien ser la descripci贸n original del algoritmo. Esto es muy com煤n en Haskell. Una definici贸n de funci贸n usualmente se asemeja mucho a la descripci贸n informal de la funci贸n. Por esto es que decimos que Haskell tiene una brecha sem谩ntica menor que otros lenguajes. Pero espera, 隆no hemos terminado todav铆a! 驴C贸mo es que las listas less y more se calculan? Bueno, recuerda que no nos importa la secuenciaci贸n en Haskell, as铆 que las hemos definido debajo de la funci贸n usando notaci贸n where (que permite usar los par谩metros de la funcion en sus definiciones). Usamos la funci贸n del preludio est谩ndar filter. No explicaremos demasiado esta parte, pero la l铆nea less = filter (<x) xs usar谩 filter (<x) xs para filtrar la lista xs. Puedes ver que realmente pasamos la funci贸n que se usar谩 para filtrar la lista a filter, un ejemplo de funciones de alto orden. La funci贸n (<x) debe leerse "la funci贸n 'menor a x'" y devolver谩 True si el elemento que se le pasa es menor que x (n贸tese qu茅 f谩cil fue construir una funci贸n al vuelo, ponemos la expresi贸n "<x", "menor a x", entre par茅ntesis y la mandamos a la funci贸n - 隆las funciones en realidad son s贸lo otro valor!). Todos los elementos que pasan la prueba son la salida de filter y terminan en less. De la misma manera, (>=x) se usa para filtrar la lista por todos los elementos mayores o iguales a x. Ahora que te han explicado la sintaxis, lee la definici贸n de la funci贸n de nuevo. Nota qu茅 poco tiempo toma lograr entender lo que la funci贸n hace. Las definiciones de funciones en Haskell explican lo que computan, no c贸mo lo hacen. Si ya te has olvidado de la sintaxis esbozada arriba, 隆no te preocupes! La cubriremos de forma m谩s completa y minuciosa en los tutoriales. Lo importante de este ejemplo es que el c贸digo Haskell es elegante e intuitivo. ===Haskell y los errores=== Hemos dicho varias veces que muchas caracter铆sticas de Haskell ayudan a disminuir la ocurrencia de errores; recapitulemos esas caracter铆sticas. Los programas en Haskell tienen menos errores porque Haskell es: * '''Puro'''. No hay efectos laterales. * '''Fuertemente tipado'''. No puede haber uso dudoso de tipos. Y no hay core dumps! * '''Conciso'''. Los programas m谩s cortos facilitan mirar una funci贸n y "captarla" de una s贸la vez, convenciendote que es correcta. * '''Alto nivel'''. Los programas de Haskell casi siempre se escriben exactamente igual que la descripci贸n del algoritmo. Lo que facilita verificar que la funci贸n haga lo que el algoritmo dice. Al codificar en un nivel de abstracci贸n superior, dejando los detalles para el compilador, se deja menos espacios para que se deslicen errores. * '''Memoria administrada'''. No hay que preocuparse por los punteros, el Garbage Collector se ocupa de ellos. El programador puede preocuparse de la implementaci贸n del algoritmo, no de administraci贸n de memoria. * '''Modular'''. Haskell ofrece m谩s "pegamento" y m谩s fuerte para componer programas a partir de m贸dulos ya desarrollados. De esta manera, los programas Haskell pueden ser m谩s modulares. Frecuentemente se puede probar que el uso de funciones modulares es correcto por inducci贸n. Combinar dos funciones que se probaron correctas dar谩 un resultado correcto (asumiendo que la combinaci贸n es correcta). Aun m谩s, la mayor铆a de las personas concuerdan en que uno piensa diferente al resolver problemas en un lenguaje funcional. Uno subdivide el problema en funciones m谩s y m谩s peque帽as y luego uno escribe esas funciones peque帽as (y "garantizadas-de-correcci贸n-casi-siempre"), que son compuestas de varias maneras para obtener el resultado final. 隆Simplemente no hay espacio para errores!
Summary:
Please note that all contributions to HaskellWiki are considered to be released under simple permissive license (see
HaskellWiki:Copyrights
for details). If you don't want your writing to be edited mercilessly and redistributed at will, then don't submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.
DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION!
Cancel
Editing help
(opens in new window)
Toggle limited content width