| Inicial | Temas | Manuales | Ejercicios | Exámenes | Documentación

Tema 4: Definición de funciones

Índice

1. Definiciones por composición

  • (isDigit c) se verifica si c es un dígito. Por ejemplo,

    λ> isDigit '2'
    True
    λ> isDigit 'a'
    False
    

    Su definición es

    isDigit :: Char -> Bool
    isDigit c = c >= '0' && c <= '9'
    
  • (even n) se verifica si =n es par. Por ejemplo,

    λ> even 6
    True
    λ> even 7
    False
    

    Su definición es

    even :: Integral a => a -> Bool
    even n =  n `rem` 2 == 0
    
  • (splitAt n xs) es el par formado por los n primeros elementos de xs y los restantes. Por ejemplo,

    λ> splitAt 2 [3,7,4,6,1]
    ([3,7],[4,6,1])
    

    Su definición es

    splitAt :: Int -> [a] -> ([a],[a])
    splitAt n xs = (take n xs, drop n xs)
    

2. Definiciones con condicionales

  • Definición del valor absoluto (con condicionales):

    abs :: Int -> Int
    abs n = if n >= 0 then n else -n
    
  • Definición del signo de un número (con condicionales anidados):

    signum :: Int -> Int
    signum n = if n < 0 then (-1)
                        else if n == 0 then 0
                                       else 1
    

3. Definiciones con ecuaciones con guardas

  • Definición del valor absoluto (con ecuaciones guardadas):

    abs n | n >= 0    = n
          | otherwise = -n
    
  • Definición del signo de un número (con ecuaciones guardadas):

    signum n | n < 0     = -1
             | n == 0    = 0
             | otherwise = 1
    

4. Definiciones con equiparación de patrones

4.1. Constantes como patrones

  • Definición de la negación:

    not :: Bool -> Bool
    not True  =  False
    not False =  True
    
  • Definición de la conjunción (con valores):

    (&&)  :: Bool -> Bool -> Bool
    True  && True  = True
    True  && False = False
    False && True  = False
    False && False = False
    

4.2. Variables como patrones

  • Definición de la conjunción (con variables anónimas):

    (&&) :: Bool -> Bool -> Bool
    True  && True =  True
    _     && _    =  False
    
  • Definición de la conjunción (con variables):

    (&&) :: Bool -> Bool -> Bool
    True  && x =  x
    False && _ =  False
    

4.3. Tuplas como patrones

  • Definición del primer elemento de un par:

    fst :: (a,b) -> a
    fst (x,_) = x
    
  • Definición del segundo elemento de un par:

    snd :: (a,b) -> b
    snd (_,y) = y
    

4.4. Listas como patrones

  • (test1 xs) se verifica si xs es una lista de 3 caracteres que empieza por 'a'.

    test1 :: [Char ] -> Bool
    test1 ['a',_,_] = True
    test1 _         = False
    
  • Construcción de listas con (:)

    [1,2,3] = 1:[2,3]
            = 1:(2:[3])
            = 1:(2:(3:[]))
    
  • (test2 xs) se verifica si xs es una lista de caracteres que empieza por 'a'.

    test2 :: [Char ] -> Bool
    test2 ('a':_) = True
    test2 _       = False
    
  • Decidir si una lista es vacía:

    null :: [a] -> Bool
    null []    = True
    null (_:_) = False
    
  • Primer elemento de una lista:

    head :: [a] -> a
    head (x:_) =  x
    
  • Resto de una lista:

    tail :: [a] -> [a]
    tail (_:xs) = xs
    

5. Expresiones lambda

5.1. Evaluación de expresiones lambdas

  • Las funciones pueden construirse sin nombrarlas mediante las expresiones lambda.
  • Ejemplo de evaluación de expresiones lambda:

    λ> (\x -> x+x) 3
    6
    

5.2. Uso de las expresiones lambda para resaltar la parcialización

  • (suma x y) es la suma de x e y.
  • Definición sin lambda:

    suma :: Int -> Int -> Int
    suma x y = x + y
    
  • Definición con lambda:

    suma' :: Int -> Int -> Int
    suma' = \x -> (\y -> x+y)
    

5.3. Uso de las expresiones lambda en funciones como resultados

  • (const x y) es x.
  • Definición sin lambda:

    const :: a -> b -> a
    const x = x
    
  • Definición con lambda:

    const' :: a -> (b -> a)
    const' x = \_ -> x
    

5.4. Uso de las expresiones lambda en funciones con sólo un uso

  • (impares n) es la lista de los n primeros números impares.
  • Definición sin lambda:

    impares :: Int -> [Int]
    impares n = map f [0..n-1]
      where f x = 2*x+1
    
  • Definición con lambda:

    impares' :: Int -> [Int]
    impares' n = map (\x -> 2*x+1) [0..n-1]
    

6. Secciones

  • Los operadores son las funciones que se escriben entre sus argumentos.
  • Los operadores pueden convertirse en funciones prefijas escribiéndolos entre paréntesis.
  • Ejemplo de conversión:

    λ> 2 + 3
    5
    λ> (+) 2 3
    5
    
  • Ejemplos de secciones:

    λ> (2+) 3
    5
    λ> (+3) 2
    5
    

6.1. Expresión de secciones mediante lambdas

  • Sea * un operador. Entonces
    • (*) = \x -> (\y -> x*y)
    • (x*) = \y -> x*y
    • (*y) = \x -> x*y

6.2. Aplicaciones de secciones

  • Uso en definiciones de funciones mediante secciones

    suma''    = (+)
    siguiente = (1+)
    inverso   = (1/)
    doble     = (2*)
    mitad     = (/2)
    
  • Uso en signatura de operadores:

    (&&) :: Bool -> Bool -> Bool
    
  • Uso como argumento:

    λ> map (2*) [1..5]
    [2,4,6,8,10]
    

7. Material complementario

El código del tema se encuentra en este enlace.

Este tema también se encuentra en los siguientes formatos:

8. Bibliografía

  • R. Bird. Introducción a la programación funcional con Haskell. Prentice Hall, 2000.
    • Cap. 1: Conceptos fundamentales.
  • G. Hutton. Programming in Haskell. Cambridge University Press, 2007.
    • Cap. 4: Defining functions.
  • B. O'Sullivan, D. Stewart y J. Goerzen. Real World Haskell. O'Reilly, 2008.
    • Cap. 2: Types and Functions.
  • B.C. Ruiz, F. Gutiérrez, P. Guerrero y J.E. Gallardo. Razonando con Haskell. Thompson, 2004.
    • Cap. 2: Introducción a Haskell.
  • S. Thompson. Haskell: The Craft of Functional Programming, Second Edition. Addison-Wesley, 1999.
    • Cap. 3: Basic types and definitions.

| Inicial | Temas | Manuales | Ejercicios | Exámenes | Documentación

José A. Alonso Jiménez

Sevilla, 07 de abril del 2024

Licencia: Creative Commons.