Unidad IV · Proyecto Disponible

Proyecto: un mismo problema en dos paradigmas

Interprete un problema de manera funcional, resuélvalo en Python imperativo, Python funcional y Haskell, verifíquelo, razone por sustitución y compare.

Objetivo de aprendizaje

Al concluir el proyecto, el estudiante será capaz de:

  1. Interpretar un problema de manera funcional con el método de seis pasos (entrada y salida, cadena de transformaciones, patrones).
  2. Resolver el mismo problema con tres estilos: Python imperativo (línea base), Python funcional y Haskell.
  3. Verificar sus soluciones con pruebas, incluidos los casos límite, y razonar por sustitución sobre un ejemplo.
  4. Explicar qué estrategia de evaluación usa cada lenguaje y cómo afecta al problema.
  5. Comparar los tres estilos y argumentar cuándo elegiría cada uno.

El producto que se entrega

Tres programas (Python imperativo, Python funcional y Haskell con sus pruebas), un informe (de tres a cinco páginas) y la evidencia registrada en esta página: el resultado de los verificadores, la tabla comparativa y la autoevaluación. Todo se exporta en un solo archivo desde el espacio de trabajo de la sección 7.


1. Planteamiento inicial

Al comenzar la unidad, la manera natural de resolver un problema de listas era un ciclo con una variable acumuladora. El proyecto sirve para comprobar si esa manera de pensar cambió.

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.


2. Elija un problema

Elija uno de los tres problemas (su docente puede asignarlos). Los tres tienen un caso límite que obliga a tomar una decisión de diseño que deberá argumentar en el informe.

Opción A. Calificaciones de un grupo

A1. Se tiene una lista de pares (nombre, calificación). A2. Obtener los nombres de quienes aprueban (6 o más). A3. Calcular el promedio del grupo. A4. Obtener el nombre de quien tiene la calificación más alta. A5. ¿Qué debe ocurrir con el promedio y con la calificación más alta de un grupo vacío? Decida y justifique.

Opción B. Análisis de un texto

B1. Se tiene un texto (una cadena). B2. Obtener sus palabras de más de tres letras, en mayúsculas. B3. Contar cuántas palabras tiene. B4. Obtener la palabra más larga. B5. ¿Qué debe ocurrir con un texto vacío o con varios espacios seguidos? Decida y justifique.

Opción C. Inventario de una tienda

C1. Se tiene una lista de ternas (producto, precio, cantidad). C2. Calcular el valor total del inventario (suma de precio por cantidad). C3. Obtener los productos agotados (cantidad 0). C4. Aplicar un descuento del 10 % a los productos de más de 100 pesos y obtener la lista de precios nuevos. C5. ¿Qué debe ocurrir con un inventario vacío? Decida y justifique.

Nota: en cualquiera de los tres, el caso límite (lista vacía) no tiene una respuesta «obvia»: el promedio de nada no está definido. Lo que se evalúa es que la decisión sea explícita, esté probada y esté explicada.


3. Interprete el problema (pasos 1 a 3 del método)

Aplique el método de seis pasos del tema 4.0 al problema elegido. Registre sus productos en la libreta.

Paso Producto que debe registrar
1. Entrada y salida Ejemplos concretos y los casos límite, con la decisión sobre cada uno
2. La cadena Una frase con verbos: «de la lista, …; …; …»
3. El patrón Cada etapa como filtrar, transformar, combinar o recursión

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.


4. La línea base y la versión funcional en Python

La línea base: la solución imperativa

Escriba primero, en su entorno, la versión con ciclos y variables: es el punto de comparación. Ejecútela paso a paso y observe qué variables cambian. Puede usar la corrida de escritorio siguiente (la lista de problemas del apuntes está en la sección 2).

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.

La versión funcional

Escriba ahora la versión funcional. Debe cumplir las reglas siguientes, que el verificador comprueba:

Requisito Qué debe contener la versión funcional
1. Piezas Al menos tres funciones pequeñas
2. Pureza Ninguna función usa variables globales, modifica listas ni imprime
3. Sin estado Ninguna función contiene while, for ni +=; las repeticiones se expresan de otra manera
4. Orden superior Usa lambda, comprensiones, map, filter o reduce
5. Recursión Al menos una función recursiva con caso base y caso recursivo
6. Documentación Al menos tres comentarios que expliquen cada pieza
7. Pruebas Se ejecuta sin errores y muestra al menos tres salidas (casos de prueba, incluido el límite)

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.

Importante: el verificador comprueba la estructura (por ejemplo, que no haya ciclos con estado), pero no puede juzgar si su descomposición en piezas es buena ni si su explicación es correcta. Eso lo valoran el informe y su docente.


5. La versión en Haskell y sus pruebas

Escriba la solución en Haskell con el subconjunto que ejecuta el sitio (tema 4.3). Debe cumplir: firma de tipo en cada definición; al menos tres funciones; al menos una función por casos con patrones; al menos una función recursiva con caso base; el uso de funciones de orden superior; y al menos tres pruebas que se cumplan.

Las pruebas se escriben una por línea: expresión => resultado esperado. El verificador evalúa cada una y le muestra, además, cuántas reducciones necesitó. Para seguir la evaluación de una expresión paso a paso, use la corrida de reducción siguiente.

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.


6. Razonamiento por sustitución y estrategias de evaluación

Razonar por sustitución

Elija una prueba pequeña de su versión en Haskell y escriba su derivación: cada línea es igual a la anterior. Puede apoyarse en la derivación que genera la corrida de reducción. Una derivación completa es la mejor evidencia de que usted entiende por qué funciona su programa, y no solo que funciona.

Comparar estrategias

Compare cuántos pasos necesita cada estrategia para una expresión de su programa y si todas terminan. Escriba sus definiciones y una expresión (por ejemplo, una prueba de la sección 5).

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.


7. Comparación, informe y autoevaluación

Diagnóstico comparado

Complete la tabla con lo que cree que ocurre en cada versión y compare con la referencia.

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.

Importante: las respuestas son una referencia didáctica. En particular, el comportamiento de Python depende de cómo se escriba el programa (el estilo imperativo y el funcional difieren), y el de Haskell, de las propiedades del lenguaje.

Planeación y redacción del informe

El informe no es un resumen de lo que se hizo, sino un argumento: explica qué se decidió, por qué y cómo se comprobó. Algunas pautas:

  • Use el método. Organice el informe según los seis pasos y haga visible la trazabilidad de cada pregunta del problema a una pieza.
  • Muestre la derivación. Una línea de razonamiento por sustitución vale más que una frase como «funciona».
  • Justifique el caso límite. La decisión sobre la lista vacía debe estar explícita, probada y explicada.
  • Compare con evidencia. Cite pasos de reducción, número de reducciones o diferencias observadas en las corridas.
  • Nombre los compromisos. Cada estilo favorece algo y cuesta algo.

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.

Importante: lo que registra en esta página solo vive en su navegador. Si cambia de equipo o borra los datos de navegación, lo perderá. Exporte el archivo con frecuencia y conserve una copia.

Autoevaluación

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.

Contraste con el planteamiento inicial

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.


8. Libreta y lista de verificación para la entrega

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.

Antes de entregar, compruebe que:

  • Eligió un problema y escribió ejemplos y casos límite, con la decisión sobre cada caso límite.
  • Escribió la cadena de transformaciones y el patrón de cada etapa.
  • Tiene la versión imperativa de referencia y puede decir qué variables cambian.
  • Su versión funcional en Python cumple los siete requisitos del verificador y está comentada.
  • Su versión en Haskell cumple los requisitos y sus pruebas se cumplen.
  • Escribió una derivación por sustitución de una prueba pequeña.
  • Comparó las estrategias de evaluación con una expresión de su programa.
  • Completó la tabla comparativa y revisó las explicaciones de las diferencias.
  • Las siete secciones del informe tienen contenido y evidencias.
  • Hizo la autoevaluación y atendió los criterios más bajos.
  • Exportó el informe y conservó una copia del archivo y de sus programas.
  • Puede explicar con sus propias palabras cada decisión de su trabajo.

9. Preguntas de reflexión

  1. ¿Qué parte de su solución imperativa tuvo que pensar de nuevo (y no solo traducir) para convertirla en funcional?
  2. ¿Qué ganó con las piezas pequeñas y puras al probar su solución? ¿Qué perdió respecto del ciclo único?
  3. ¿Qué decisión de diseño de Haskell (por ejemplo, la pureza garantizada o la evaluación perezosa) le facilitó el trabajo y cuál se lo dificultó?
  4. Si el problema tuviera un millón de datos, ¿qué cambiaría en cada versión? Considere la memoria, la recursión y la pereza.
  5. ¿En qué situaciones elegiría el estilo imperativo, el funcional en Python o Haskell? Justifique.

10. Lecturas recomendadas

  • Hutton, G. (2016). Programming in Haskell (2nd ed.). Cambridge University Press.
  • Bird, R. (2015). Thinking functionally with Haskell. Cambridge University Press.
  • Hughes, J. (1989). Why functional programming matters. The Computer Journal, 32(2), 98–107.
  • Sebesta, R. (2015). Concepts of programming languages (11th ed.), capítulo sobre lenguajes de programación funcional. Pearson.
  • Python Software Foundation. Functional Programming HOWTO. Acceso libre en docs.python.org.