Haskell Hero
Haskell Hero es un manual interactivo del lenguaje Haskell para principiantes.
|
Tipo de funciones compuestasUn ejemplo simple 1
¿Qué es el tipo de la función
En la lección Funciones útiles podéis encontrar esta función representada por una caja. Para repetir: ¿Qué es el tipo de función? Es una definición de tipos de valores que entran en la función y el tipo del valor al que se evalúa la función. Todas las partes están separadas por flechas El tipo de una función compuesta consta entonces de valores que entran al principio y de las que se devuelven al fin. Valores de resultados intermedio no nos interesan.
Como podemos ver en el imagen de la otra lección, la función odd . snd :: (a, Integer) -> Bool Un ejemplo simple 2
¿Qué es el tipo de la función
La función head [3,4,5] ~> 3
Sin embargo, si aplicamos la función (head . head) [3,4,5] ~> head (head [3,4,5]) ~> head 3 ~/>
Quisieramos que la primera aplicación de la función (head . head) [[3,10,14], [8,4,13,15], []] ~> head (head [[3,10,14], [8,4,13,15], []]) ~> head [3,10,14] ~> 3
Ya que el tipo de lista de entrada no es importante para la función head . head :: [[a]] -> a Convertimos en pointwise
Pointwise es una notación opuesta a la notación en estilo pointfree. En la expresión pointfree la lambda se sustituye por operadores Para la conversión de pointfree a pointwise necesitamos solo tres reglas:
Un ejemplo más complejo
Definid el tipo más general de la función Esta tarea se puede resolver de muchas maneras. Aquí mostramos la conversión de la función al estilo pointwise y después la declaración de tipo de ella.
Primero hay que decidir donde poner las paréntesis.
((.(,)) . (.)) . (,) o (.(,)) . ((.) . (,)) En la tabla de prioridades y asociación encontramos que (.) asocia de la derecha, lo que significa que las paréntesis se deberían poner de manera siguiente:
(.(,)) . ((.) . (,)) Ahora ya podemos empezar con la propia conversión al estilo pointwise. Durante la conversión al estilo pointfree estabamos quitando los parámetros. Aquí vamos a añadirlos. Aplicamos entonces la nuestra función al parámetro x .
\x -> ((.(,)) . ((.) . (,))) x La expresión la modificamos según la definición de (.) : (nota: el signo ===> es solo un signo definido por nosotros para la reducción de la notación, no es un operador de Haskell. Significa "vamos a convertir esto en esto")
\x -> ((.(,)) . ((.) . (,))) x (--f--- . -----g-----) x ===> \x -> (.(,)) (((.) . (,)) x) -- f - (---- g ---- x) Ahora utilizamos el hecho de que (+5) 3 es lo mismo que 3 + 5 .
\x -> (.(,)) (((.) . (,)) x) (+ 5 ) (----- 3 -----) ===> \x -> (((.) . (,)) x) . (,) (----- 3 -----) + 5 Ahora modificamos ((.) . (,)) x según la definición de (.) .
\x -> (((.) . (,)) x) . (,) ( f . g ) x ===> \x -> ((.) ((,) x)) . (,) f ( g x) Ahora ya hemos convertido todo lo que podíamos pero la función todavía no está en el estilo pointwise. Añadimos entonces un nuevo parámetro general, por ejemplo y .
\x y -> (((.) ((,) x)) . (,)) y Ahora podemos utilizar la definición de (.) otra vez.
\x y -> (((.) ((,) x)) . (,)) y (----- f ----- . g ) y ===> \x y -> ((.) ((,) x)) ((,) y) ----- f ----- ( g x) En este momento tenemos la expresión en la forma ((+) 3) 5 y lo vamos a convertir en 3 + 5 .
\x y -> ((.) ((,) x)) ((,) y) ((+) -- 3 --) -- 5 -- ===> \x y -> ((,) x) . ((,) y) -- 3 -- + -- 5 -- Ahora no podemos modificar la notación de ninguna manera pero todavía no es una expresión que se evalúe completamente. Por eso aplicamos toda la expresión a un argumento nuevo que llamamos por ejemplo z .
\x y z -> (((,) x) . ((,) y)) z Después quitamos el operador (.) de manera típica.
\x y z -> (((,) x) . ((,) y)) z (-- f -- . -- g --) x ===> \x y z -> ((,) x) (((,) y) z) -- f -- (-- g -- x) Todos los operadores (.) están quitados, ahora nos queda solo convertir la definición en la notación infija para que sea más claro. Primero convertimos la subexpresión ((,) y) z .
\x y z -> ((,) x) (((,) y) z) ((+) 3) 5 ===> \x y z -> ((,) x) (y,z) 3+5 Y luego toda la expresión. \x y z -> ((,) x) (y,z) ((+) 3) - 5 - ===> \x y z -> (x,(y,z)) 3+ -5- ¿A qué hemos llegado?
No podíamos decir nada sobre la función
¿Qué es entonces el tipo de la función (.(,)) . (.) . (,) :: a -> b -> c -> (a,(b,c)) |