Documente Academic
Documente Profesional
Documente Cultură
Haskell es un lenguaje funcional (donde todo se hace con llamadas a funciones), estático,
implícitamente tipado (los tipos los revisa el compilador, pero no hace falta declararlos),
perezoso (nada se hace hasta que es completamente necesario). Los lenguajes populares más
parecidos son la familia ML (que no son, sin embargo, lenguajes perezosos).
2 Expresiones simples
Es posible escribir varias expresiones matemáticas directamente en ghci y obtener un
resultado. Prelude es el prompt por defecto de GHCi.
Prelude> 3 * 5
15
Prelude> 4 ^ 2 - 1
15
Prelude> (1 - 5)^(3 * 2 - 4)
16
++
.
Prelude> "Hello"
"Hello"
Prelude> "Hello" ++ ", Haskell"
"Hello, Haskell"
Las funciones se llaman colocando los argumentos directamente después del nombre de la
función. No hay paréntesis en la llamada a la función:
Prelude> succ 5
6
Prelude> truncate 6.59
6
Prelude> round 6.59
7
Prelude> sqrt 2
1.4142135623730951
Prelude> not (5 < 3)
True
Prelude> gcd 21 14
7
3 La consola
Las Acciones I/O se pueden usar para leer y escribir en la consola. Algunas son:
do
. Las acciones se separan con punto y coma.
Prelude> do { putStr "2 + 2 = " ; print (2 + 2) }
2 + 2 = 4
Prelude> do { putStrLn "ABCDE" ; putStrLn "12345" }
ABCDE
12345
String
)o
readLn
(que retorna un valor de cualquier tipo que se desee). El símbolo
<-
se usa para asignar un nombre
llaves y los punto y coma, la indentación se vuelve importante. Esto no funciona muy bien
en ghci, pero intente poniéndolo en un fichero (por ejemplo, Test.hs) y compilelo.
Puede compilar con ghc --make Test.hs, y el resultado se llamará Test. (en Windows,
Test.exe) Se tiene una expresión
if
como un extra. El primer carácter no blanco luego de
do
es especial. En este caso, es la p en
putStrLn
. Cada linea que empieza en la misma columna que la
p
es otra instrucción en el bloque
do
. Si se indenta más, se vuelve parte de la instrucción anterior. Si se indenta menos, se termina
el bloque
do
. Esto se llama
"layout", y Haskell lo usa para evitar el uso de puntos y coma y llaves todo el
por esta razón. Si empiezan en la misma columna, serán instrucciones separadas, lo que sería
incorrecto).
(Nota: No indente con tabulaciones si está usando "layout". Técnicamente funcionará si usa
tabulaciones de 8 espacios, pero no es una buena idea. Tampoco use fuentes proporcionales
que, aparentemente algunas personas usan, incluso para programar!).
4 Tipos Simples
Hasta ahora no se a mencionado ni un solo tipo. Esto es por que Haskell hace inferencia de
tipos. Generalmente no es necesario declararlos a menos que se así se quiera. Si desea
declarar tipos, se puede usar
::
para hacerlo.
Prelude> 5 :: Int
5
Prelude> 5 :: Double
5.0
Tipos (y las clases de tipos, de las cuales se hablará luego) siempre empiezan con una letra
mayúscula. Las variables siempre empiezan con una letra minúscula. Esta es una regla del
lenguaje, no una |convención.
Se puede preguntar a ghci que tipo se ha elegido para algo. Esto es útil por que generalmente
no hay necesidad de declarar los tipos.
Prelude> :t True
True :: Bool
Prelude> :t 'X'
'X' :: Char
Prelude> :t "Hello, Haskell"
"Hello, Haskell" :: [Char]
(En caso de que lo haya notado,
[Char]
es otra forma de decir
String
. Vea la sección sobre listas luego.)
Prelude> :t 42
42 :: (Num t) => t
Prelude> :t 42.0
42.0 :: (Fractional t) => t
Prelude> :t gcd 15 20
gcd 15 20 :: (Integral t) => t
se puede usar como cualquier tipo numérico. (Esta es la razón por la que podemos
declarar
como
Int
o como
Double
).
42.0
gcd 15 20
(que es una llamada de función) puede ser cualquier tipo integral, pero no un tipo
fraccionario.
Existen 5 tipos numéricos en el "preludio" de Haskell (la parte de la librería que se obtiene
sin tener que importar nada):
Int
Integer
Float
Double
Rational
es un tipo fraccionario, sin error de redondeo.
igual manera.
Prelude> ()
()
Prelude> :t ()
() :: ()
C. Se puede retornar
()
desde una acción de I/O cuando no se
5 Datos estructurados
Los tipos de datos básicos se pueden combinar fácilmente de dos maneras: listas, que van
entre [corchetes], y tuplas, que van entre (paréntesis).
Las listas se usan para mantener múltiples valores del mismo tipo.
Prelude> [1, 2, 3]
[1,2,3]
Prelude> [1 .. 5]
[1,2,3,4,5]
Prelude> [1, 3 .. 10]
[1,3,5,7,9]
Prelude> [True, False, True]
[True,False,True]
Las tuplas mantienen un numero fijo de valores, que pueden tener tipos distintos.
Las listas se usan mucho en Haskell. Has varias funcionas que haces cosas útiles con ellas.
Prelude> [1 .. 5]
[1,2,3,4,5]
Prelude> map (+ 2) [1 .. 5]
[3,4,5,6,7]
Prelude> filter (> 2) [1 .. 5]
[3,4,5]
6 Definición de funciones
Habíamos escrito la definición de acciones IO, llamada
main
:
main = do putStrLn "What is 2 + 2?"
x <- readLn
if x == 4
then putStrLn "You're right!"
else putStrLn "You're wrong!"
función y llamándola
factorial
. También agregaré
un modulo de cabecera.
$ ./Test
What is 5! ?
120
You're right!
Ahí tenemos una función. Tal como las que vienen por defecto, se puede llamar
como
factorial 5
sin paréntesis.
$ ghci Test.hs
<< GHCi banner >>
Ok, modules loaded: Main.
Prelude Main> :t factorial
factorial :: (Num a) => a -> a
Los tipos de las funciones se escriben como el tipo del los argumentos, seguidos
de
->
, y luego el tipo del resultado. (Este ejemplo también tiene la clase de tipo
Num
).
factorial 0 = 1
factorial n = n * factorial (n - 1)
7 Sintaxis conveniente
Algo más de sintaxis es útil.
otra vez. Se puede usar {llaves}, y separar los nombres con punto y comas, si se prefiere).
8 Usando librerías
Todo lo que se ha usado hasta ahora es parte del Preludio, que es un conjunto de funciones
Haskell que siempre están disponibles sin solicitarlas.
errorsPerLine = M.fromList
[ ("Chris", 472), ("Don", 100), ("Simon", -5) ]
En un sistema UNIX, se puede necesitar ser root para esta ultima parte.