Haskell interpretado, por ejemplo con ghci, puede ser utilizado como calculadora. Se pueden utilizar los operadores '+', '-', '*', '/', '**', '^' y '^^'. En realidad no son operadores; son funciones que toman dos argumentos, y al ponerlos entre paréntesis se pueden emplear con la sintaxis usual.
Prelude> 2 + 3 5 Prelude> (+) 2 3 5 Prelude> (7-4)*6 18 Prelude> (*) ((-) 7 4) 6 18
El operador '/' solamente opera sobre valores fraccionarios, como se puede ver en su declaración de tipo:
Prelude> :t (/) (/) :: (Fractional a) => a -> a -> a Prelude> 3/4 0.75
El operador '**' toma exponente flotante, '^' toma exponente entero de un entero, y '^^' toma exponente entero pero de un fraccional:
Prelude> :t (**) (**) :: (Floating a) => a -> a -> a Prelude> :t (^) (^) :: (Num a, Integral b) => a -> b -> a Prelude> :t (^^) (^^) :: (Fractional a, Integral b) => a -> b -> a Prelude> 5.5**3.1 197.2987516692004 Prelude> 3^4 81 Prelude> 3 ^^ 4 81.0
Las declaraciones de tipos consisten de dos partes. La primera, e.g. (Num a, Integral b), es una declaración de clases de tipos. Significa que el tipo 'a' puede ser cualquiera mientras sea el tipo de un número; y el tipo 'b' puede ser cualquiera, mientras sea el tipo de un número entero.
La segunda parte consiste de los tipos de los argumentos unidos por flechas '->'. Si el tipo es 'a -> a -> a' significa que la función toma dos valores del tipo 'a' y regresa uno del mismo tipo.
¿Pero qué pasa si ponemos paréntesis para entender ese 'a -> a -> a' como 'a -> (a -> a)'? Lo que dice ahí es que ahora es una función que toma un solo argumento de tipo 'a'; ¡pero regresa otra función, que toma un valor de tipo 'a' y regresa otro del mismo tipo! En Haskell esto es válido. Un ejemplo.
Prelude> :t (+) 3 (+) 3 :: (Num t) => t -> t Prelude> ((+) 3) 4 7
El '(+) 3' se puede leer ahora como "función que suma 3 a su argumento". Existe una forma abreviada de escribir esta clase de reducción, a la que se denomina secciones:
Prelude> :t (+3) (+3) :: (Num a) => a -> a Prelude> (+3) 4 7 Prelude> (/3) 12 4.0
Por último, la verdadera utilidad de las secciones se aprecia al realizar composición de funciones con el operador (.), que compone f(g(x)) <-> (f.g) x:
Prelude> (((5*3)+1)/2) 8.0 Prelude> (/2).(+1).(*3) $ 5 8.0
El operador '$' empleado arriba es el operador de aplicación. Garantiza que el lado izquierdo y el lado derecho sean completamente evaluados antes de aplicar el lado izquierdo sobre el lado derecho. Aquí se utiliza para evitar poner más paréntesis.
La utilidad de esta forma de composición no se limita a hacer más legible la secuencia de operaciones. Hecho de la primera forma, el argumento (5) está oculto en medio de la operación. De la segunda, está al final. Es mucho más accesible si la función se va a usar varias veces con diferentes valores.
