¿Es el sistema de tipos de Haskell un obstáculo para comprender la programación funcional? [cerrado]

33

Estoy estudiando Haskell con el propósito de comprender la programación funcional, con la expectativa de que aplique la información que obtengo en otros idiomas (Groovy, Python, JavaScript principalmente).

Elegí Haskell porque tenía la impresión de que es muy puramente funcional y no permitiría depender del estado.

No elegí aprender Haskell porque estaba interesado en navegar en un sistema de tipo extremadamente rígido.

Mi pregunta es la siguiente: ¿Es un sistema de tipo fuerte un subproducto necesario de un lenguaje funcional extremadamente puro, o esta es una elección de diseño no relacionada en particular para Haskell?

Eric Wilson
fuente
66
Si no desea escribir nada explícitamente, no necesita escribir nada explícitamente. Haskell puede inferir tipos muy bien por sí solo. Y no es que vaya a tener una sola variable que posiblemente almacene dos tipos incompatibles.
Anon
44
@Anon sí, pero sus listas deben ser homogéneas. Confía en mí, este tipo de cosas pueden interferir, incluso con inferencia de tipos.
Eric Wilson
13
@FarmBoy y ¿qué tiene de malo el uso de Maybe? Java realmente te hace usar Quizás en todas las clases, lo cual es algo extraño.
alternativa el
3
Y si realmente desea usar una lista heterogénea, por supuesto, puede usar tipos de datos algebraicos.
alternativa el
1
@mathepic en este punto realmente hemos perdido la noción de mi pregunta original, que era una pregunta perfectamente válida.
Eric Wilson

Respuestas:

40

Creo que comprender el sistema de tipos de Haskell es un amplificador para comprender la programación funcional.

Lo que pasa con la programación puramente funcional es que, en ausencia de efectos secundarios, que le permiten hacer todo tipo de cosas implícitamente, la programación puramente funcional hace que la estructura de sus programas sea mucho más explícita.

Haskell evita que empujes cosas debajo de la alfombra, te obliga a lidiar explícitamente con la estructura de tu programa y te enseña un lenguaje para describir estas estructuras: el lenguaje de los tipos. Entender los tipos, particularmente los tipos ricos como es Haskell, te hará un mejor programador en cualquier idioma.

Si Haskell no estuviera fuertemente tipado, conceptos como mónadas, functores aplicativos y similares nunca se habrían aplicado a la programación.

Waquo
fuente
2
Esta es una buena respuesta, agrego que si bien el sistema de tipos puede parecer inusual al principio, más adelante, cuando comience a aprender los conceptos más avanzados, verá que hay ciertas cosas que solo se pueden hacer debido a la adherencia a ese tipo sistema (agregue STM y datos paralelos a la lista anterior). Las cosas que serían no iniciadoras en otros sistemas de tipo encajan naturalmente con el sistema Haskell. Mi consejo: quédate con él por un tiempo, deja que se hunda con el tiempo (no es un lenguaje "abarrotado").
anon
2
Sé que esta es una respuesta súper antigua, pero en realidad no estoy de acuerdo. Creo que, tan explícito como algunas cosas pueden estar en el lenguaje, el sistema de tipos, especialmente con mónadas como State y Parsec, barre una TONELADA de cosas debajo de la alfombra. Esto en realidad está interfiriendo mucho con mi capacidad de aprender las bibliotecas del idioma.
Savanni D'Gerinel
44
@ SavanniD'Gerinel: Creo que en esta respuesta "meter cosas debajo de la alfombra" no significa agregar funcionalidad implícita (lo que Haskell hace de manera controlada, por ejemplo, a través de mónadas, y que ayuda a reducir la repetitiva), sino que permite algún código hacer algo que no se espera que haga. Por ejemplo: una función pura en Haskell nunca tendrá efectos secundarios. Período. En muchos otros idiomas, puede prometer esto en la documentación de una función, pero nada en su idioma le impedirá introducir algunos efectos secundarios en algún lugar de su código.
Giorgio
33

El lenguaje funcional más dinámicamente tipado es posiblemente Scheme. Dicho esto, el sistema de tipos de Haskell es un indicador de su pureza. Se trata de "¿cómo se mide la pureza?". El sistema de tipos de Haskell le permite acordonar fácilmente acciones impuras IO. Para hacer eso, necesita un sistema de tipo estático.

Pero digamos que el sistema de tipos de Haskell no tiene nada que ver con la programación funcional. Todavía sería el colmo de la arrogancia afirmar que el sistema de tipos no lo ayudaría en este esfuerzo educativo. El sistema de tipos de Haskell es rico y complejo, y aún más interesante en comparación con los sistemas de tipos de C ++ y OCaml.

¿Es un obstáculo? No, creo que es un activo. Trate de considerar cómo lidiar con la pereza de Haskell sin, IOpor ejemplo.

Logan Capaldo
fuente
8
El sistema de tipos de +1 Haskell puede ser tu amigo una vez que te acostumbres.
Larry Coleman
"Para hacer eso, necesitas un sistema de tipo estático". De Verdad?
Jon Harrop
1
"Tanto más interesante en comparación con los sistemas de tipo de C ++ y OCaml". ¿Ha estudiado los módulos de primer orden de primer nivel de OCaml y el sistema de objetos inferidos estructuralmente tipificados y las variantes polimórficas?
Jon Harrop
2
@ JonHarrop o un sistema de efectos o alguna forma de medir / evaluar la pureza. Sí, por eso es interesante compararlos. Diferentes elecciones hacen para diferentes idiomas.
Logan Capaldo
20

Clojure es de tipo dinámico y casi tan puro como Haskell, por lo que hay un buen argumento de que el sistema de tipos de Haskell era más una elección de diseño que un requisito absoluto. Ambos definitivamente tienen sus puntos fuertes, por lo que es posible que desee considerar Clojure si realmente no le gusta la rigidez de Haskell (pero vea a continuación).

Cuando comencé a usar Haskell, consideraba que el sistema de tipos era molesto, y solo lo toleraba debido a la inferencia de tipos. Pronto descubrí que muchos de los errores tipográficos del compilador se quejaban de cosas que no habrían funcionado de todos modos, incluso si el compilador me hubiera permitido hacerlas (por ejemplo, usar accidentalmente map en lugar de concatMap). Luego descubrí que los programas que pasaron la verificación de tipo generalmente eran correctos, o al menos casi correctos. Incluso tuve una fase diferida donde realicé la refactorización cambiando un tipo de función y dejando que el compilador me dijera qué más necesitaba ser cambiado. Finalmente, me di cuenta de que el sistema de tipos de Haskell era realmente muy expresivo y comencé a diseñar mis programas en torno a los tipos. Ese es el Santo Grial de Haskell.

Larry Coleman
fuente
Otra cosa a tener en cuenta: aprendí programación funcional usando Scheme y Haskell casi al mismo tiempo (el primero para una clase y el segundo para divertirme). He descubierto que la recursividad entendimiento era mucho más fácil con la coincidencia de patrones de Haskell que con ifs y condS en el esquema, que imagino también se traslada a Clojure.
Tikhon Jelvis
@Larry Coleman: +1 por describir con precisión mi propia experiencia con los sistemas de tipos: primero C ++, luego Ocaml y ahora mi propio lenguaje Felix. Sí, todavía refactorizo ​​persiguiendo errores del compilador.
Yttrill
8

El sistema de tipos de Haskell es clave para su capacidad de aislar los efectos del código puro. A menos que pueda aislar los efectos de otra manera o eliminarlos por completo, un sistema de tipo estático fuerte es un requisito para la programación funcional pura.

Haskell es un muy buen ejemplo de un lenguaje con un sistema de tipo fuerte y estático. Si desea una educación amplia y completa en ciencias de la computación y diseño de lenguaje de programación en particular, Haskell sería una excelente opción como uno de los idiomas que debe aprender.

El sistema de tipos no debería ser un gran obstáculo. Las personas que programan tienden, incluso cuando usan lenguajes dinámicos, a seguir convenciones de escritura que pueden codificarse usando el sistema de tipos de Haskell. Haskell también presenta inferencia de tipos que alivia la verbosidad en comparación con lenguajes como C ++ y Java. Cuando recibe un mensaje de error, el compilador solo le dice en tiempo de compilación lo que un lenguaje con tipos dinámicos le diría en tiempo de ejecución.

Lo contrario de un sistema de tipo dinámico es un sistema de tipo estático, no un sistema de tipo fuerte. Un sistema de tipo fuerte es lo opuesto a un sistema de tipo débil.

dan_waterworth
fuente
1
Por ejemplo, C está estática pero débilmente tipada. Tiene tipos, pero es fácil subvertir el sistema de tipos por completo, jugar con las representaciones subyacentes específicas de la máquina, etc. Muchos lenguajes de tipo dinámico OTOH están muy bien tipados: pocos modelos implícitos, pocas formas (si las hay) de subvertir el sistema de tipos.
Steve314
4

Te dice de inmediato cuando cometes errores tontos. Esto es útil. He estado trabajando en Racket (Scheme) este último período, y en varias ocasiones pasé un s-exp sin analizar en el que esperaba un análisis analizado para alguna función en mi intérprete, y solo apareció en mi conjunto de pruebas de tamaño mediano. Si tuviera algo de tipeo estático, me habría llamado la atención de inmediato.

Por supuesto, el sistema de tipos no puede detectar realmente los errores lógicos, pero la cantidad de formas en que puede equivocarse disminuye considerablemente.

Además, la inferencia de tipos le permite ignorar el sistema de tipos si lo desea. Todavía está allí, pero no requiere una entrada activa de su parte. Todavía es útil comprender los tipos de funciones, pero el código correcto funcionará bien.

La pureza de Haskell está codificada en su sistema de tipos. La mónada IO es una construcción de nivel de tipo que evita que el código impuro se filtre en funciones puras, por lo que la pureza está garantizada por el sistema de tipos.

Theo Belaire
fuente
8
Si crees que puedes ignorar el sistema de tipos de Haskell, entonces creo que no has codificado mucho Haskell.
Eric Wilson
No ignore tanto como ignórelo tanto como escriba la función, cárguela en GHCi y continúe: t. Pero todavía necesitará agregar algunas funciones de Integral u otras funciones a veces.
Theo Belaire
1
Tyr, incluso con la inferencia de tipos, el 90% de usar y codificar las funciones de Haskell está logrando que las cosas se mezclen entre sí, lo que requiere una comprensión de su sistema de tipos y mensajes de error de verificación de tipos arcanos. Incluso ": t" no es una solución mágica, solo el primer paso para comprender cómo hacer que el programa se compile.
Andres F.
Bueno, algunas partes son desordenadas, estoy de acuerdo. Realmente creo que las cosas numéricas en el preludio podrían limpiarse y repararse, porque tal como están las cosas, es un desastre terrible. Pero la mayoría de los aspectos funcionales clave son bastante limpios. map, filter, foldr / l y otras divertidas funciones funcionales funcionan bastante bien.
Theo Belaire
2

Ser un lenguaje "funcional" significa (aparte de otras cosas) que las funciones son objetos de primera clase en el lenguaje.

Ser un lenguaje "puro" significa que las funciones son funciones matemáticas (a diferencia de los procedimientos): dada la misma entrada, siempre producen la misma salida.

Un "lenguaje funcional puro" es aquel en el que se mantienen los dos anteriores. No conozco un " lenguaje puramente funcional".

Un sistema de tipo fuerte es una forma limpia de tener un lenguaje puro pero práctico. Los tipos ayudan al compilador a descubrir optimizaciones, aparte de asegurar aún más la corrección. (Pero esa no es la única forma: clojure es puro, pero no tiene un sistema de tipo tan fuerte como Haskell).

Si el sistema de tipos te molesta, te sugiero que pruebes un lenguaje más dinámico, como Scheme, o que utilices el sistema de inferencia de tipos de Haskell.

pyNem
fuente
0

Sí, el sistema de tipos es un activo increíble. Sería muy difícil incluso describir cómo funcionan las mónadas o cómo funcionan algunos combinadores sin el sistema de tipos. Considere cuántos tutoriales sobre Haskell le piden primero que considere el tipo de función en cuestión con a: t en REPL. Eso simplemente no está disponible para usted en un lenguaje de tipo dinámico. Claro, toda la complejidad del sistema de tipos sigue ahí. Una mónada sigue siendo una mónada. Pero el lenguaje ha decidido lavarse las manos y no proporcionar ninguna ayuda. Estás solo, amigo. No estoy tocando idiomas escritos dinámicamente. Los amo mucho. Scheme es una herramienta eléctrica por excelencia. Pero notará que cuando hablamos de cosas como mónadas en lenguajes dinámicos, a menudo inventamos una notaciónpara describir el tipo de procedimientos. Un programador funcional luchará con tipos de una forma u otra. El verificador de tipo de Haskell solo le brinda buenas herramientas para aprender cómo hacerlo.

Ara Vartanian
fuente