Cursosā€Ž > ā€ŽCursadas Anterioresā€Ž > ā€Ž2010ā€Ž > ā€ŽJueves MaƱanaā€Ž > ā€ŽFuncionalā€Ž > ā€Ž

Clase 3

Recursividad

  • Arrancamos trabajando con definiciones recursivas sencillas, como factorial y Fibbonacci. Sobre eso pudimos ver la idea de caso recursivo y los casos de corte.
  • Al crear funciones que tienen mĆ”s de una definición, eso nos obliga a ver la diferencia con lógico si lo comparamos con un predicado que tenga varias clĆ”usulas. La principal diferencia es que en lógico al trabajar con relaciones estas pueden tener mĆ”s de un resultado, mientras que en funcional siempre una función va a tener un Ćŗnico resultado; y por lo tanto de todas las definiciones disponibles sólo evaluarĆ” una.
    ¿CuÔl evalúa? La primera que matchee.
  • A continuación hicimos la función par y aprovechamos para repasar compoisción al ver el caso recursivo. Tiene algunas sutilezas esa definición, la forma mĆ”s fĆ”cil que encontrĆ© para que el Haskell la acepte es:
    par 0 = True
    par 1 = False
    par n = (not . par . subtract 1) n

Recursividad sobre listas

  • Recordamos que al igual que en prolog, las listas son estructuras recursivas ya que se componen de una cabeza y una cola que a su vez es una lista (salvo la lista vacĆ­a, claro).
  • Con eso en mente podemos intentar hacer algunas funciones simples como length, nth0 , indexOf, map y any.
  • A continuación nos gustarĆ­a hacer la función filter, pero para eso debemos incorporar un concepto nuevo: guardas. Las guardas nos dan una forma alternativa al pattern matching para definir funciones en varias partes, por ejemplo:
    filter _ [] =[]
    filter f (x:xs) | f xĀ Ā Ā Ā Ā Ā  = x : filter f xs
    Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā  | otherwise =Ā Ā Ā Ā  filter f xs

  • Sabiendo eso podemos probar nosotros con la función find (ojo, sin usar filter, es para practicar recursividad).

Fold

  • Finalmente definimos las funciones sumatoria, productoria y "andtoria" (hacer and de toda una lista de booleanos). Vemos que tienen una estructura muy similar:
    sumatoria [] = 0
    sumatoria (x:xs) = x + sumatoria xs

    productoria [] = 1
    productoria (x:xs) = x * productoria xs

    andtoria [] = True
    andtoria (x:xs) = x && andtoria xs

  • MĆ”s concreatamente las tres tienen la misma estructura, y lo que cambia es:
    • La operación que hago entre los elementos (suma, multiplicación, and)
    • El valor base para la lista vacĆ­a (0, 1 o True).

  • Entonces eso nos permitirĆ­a hacer una Ćŗnica función que reciba esas diferencias como parĆ”metro, en Haskell esa función se llama foldr:
    foldr f z [] = z
    foldr f z (x:xs) = f x (foldr f z xs)

  • Con esa definición ahora podemos redefinir las anteriores de la siguiente manera:
    sumatoria = foldr (+) 0
    productoria = foldr (*) 1
    andtoria = foldr (&&) True

  • ĀæQuĆ© relación hay entre las operaciones y los valores base?
    Podemos ver que cada valor base es el valor neutro de la operación que podemos hacer.

  • TambiĆ©n se puede mencionar que el fold es mĆ”s genĆ©rico que lo que hicimos hasta ahora ya que pusimos sólo ejemplos en los que el valor devuelto es del mismo tipo que los elementos de la lista, esto no tiene que ser asĆ­ siempre. Pero vamos a dejar esos ejemplos para mĆ”s adelante.

  • Un ejemplo que sĆ­ podemos ver es el de la función mĆ­nimo. La diferencia entre esta función y las anteriores es que no es posible elegir un valor entero que sea neutro de la operación "mĆ­nimo entre dos valores". La forma mĆ”s prolija de solucionar este inconveniente es tomar como valor inicial al primer elemento de la lista.
    Eso en Haskell estÔ hecho con la función foldr1:
    foldr1 f (x:xs) = foldr f x xs

    Eso nos permite luego definir la función minimum así:
    minimum = foldr1 min

    Donde min es la función que me da el mínimo entre dos valores (ya viene con el Haskell)

Ejercicios para practicar

  • Lo que me parece mĆ”s importante a esta altura es completar toda la guĆ­a nĆŗmero 2, que tiene ejercicios de composición, aplicación parcial y orden superior incluyendo listas y fold.
  • Para practicar recursividad pueden mirar la guĆ­a nĆŗmero 3.