Sunteți pe pagina 1din 8

Uso de Haskell online

Es muy prctico usar Haskell de manera online, pero a veces nos resulta dificultoso si no
sabemos la sintaxis para ejecutar el cdigo de manera online, lo que va a acarrear que el
programa tire error y no podamos ejecutar nuestro cdigo. Este manual busca aclarar la forma
de poder ejecutar, sin que el programa tire error y el uso de Haskell online no se vuelva
frustrante, sino que por el contrario, se vuelva ameno y cmodo.
Empezamos dirigindonos a la pgina: http://rextester.com/l/haskell_online_compiler

All por defecto nos encontramos con el siguiente cdigo:


--ghc 7.10
main = print $ "Hello, world!"

Que significa que se imprima, despliegue o muestre en pantalla la cadena "Hello, world!"

Pulsamos el botn que se encuentra en la parte inferior de la pgina.


Veremos que no tir errores de compilacin y que hizo lo que desebamos

Leer e introducir nmeros desde el cdigo


Ahora vamos a trabajar con nmeros que especificaremos desde el cdigo
Queremos compilar un cdigo que muestre el factorial de un nmero.
Tenemos el siguiente cdigo

fac 0 = 1
fac n = n * fac (n-1)
main = print (fac 42)

Pegamos este cdigo en la ventana de la aplicacin y le damos en el botn de ejecutar


Nos va a dar 1405006117752879898543142606244511569936384000000000 que es el
resultado del factorial de 42.
Leer e introducir dos o ms nmeros desde teclado
Podemos hacer tambin que lea dos nmeros desde teclado, en una funcin que requiera leer
dos nmeros. Por ejemplo tenemos la funcin suma, que lo que hace es recibir dos enteros y
devolver la suma de ellos.

suma :: Int -> Int -> Int


suma x y = x+y
main = print (suma 4 3)

Si ejecutamos el cdigo nos va a dar 7 que es el resultado correcto.

Con lo explicado anteriormente, es fcil deducir como se puede programar para introducir tres o
ms nmeros en el cdigo, para funciones que requieran tres o ms argumentos, por ejemplo,
para leer variables x, y y z en una funcin suma que tome tres nmeros se usara print (suma
4 3 8)

Introducir un nmero desde cuadro de texto input del programa


Lo ms prctico y para no tener que modificar el cdigo es poder lograr que el programa lea el
nmero desde la casilla de texto input, y no prefijarlo en el cdigo.
Lo primero que temeos que entender es que hay una palabra clave para leer un nmero desde
teclado. Dicha palabra clave es getLine

Ejemplo: Queremos leer una variable llamada x desde teclado: Entonces hacemos x <-
getLine

Lo otro que tenemos que entender que esta es una funcin IO (Input-Output) es decir entra un
elemento (puede ser esta un nmero, carcter, cadena) y sale otro elemento de otro tipo

Esto se debe especificar arriba de la instruccin main = do como main :: IO ()


Lo que significa que el main devuelve un IO

El programa (incompleto) estara quedando de la siguiente forma

fac 0 = 1
fac n = n * fac (n-1)
main :: IO ()
main = do
n <- getLine --Le pedimos al programa que obtenga la lnea
donde est el valor de la variable x

Como dije, el programa est incompleto y va a tirar error, porque nunca aplicamos la variable n
a la funcin fac

Si agregamos la instruccin print (fac n) debajo tambin va a tirar error , porque como
dice el mensaje de error: No hay instancia para (Num String) que surja de un uso de
'fac'

Para corregir el programa debemos agregar la siguiente sintaxis:

putStrLn (show (fac (read n)))

Donde: putStrLn indica poner en una lnea


show: Mostrar, en este caso por pantalla
fac: El nombre de la funcin
read: Leer una variable en este caso va a ser la variable llamada n

Nota: No es necesario especificar el tipo de dato, aunque si se lo incluye no va a tirar error.


Para escribirlo en forma ms funcional, es posible utilizar transformaciones mnada, para pasar
de esa manera
main = getLine >>= (\n -> putStrLn(show (fact (read n))))

El operador ">>=" obtendr el valor del resultado de la primera accin mondica (aqu es la
accin IO de obtener entrada) y lo aplicar a la funcin de la derecha (aqu est la funcin
lambda que lee la entrada como Entero, aplica su funcin y lo devuelve a putStrLn, que lo
imprime en la pantalla). La sintaxis "do" es esencialmente solo un agregado sintctico para estas
operaciones mondicas, por lo que no afectar la ejecucin o el rendimiento del programa.
Se puede ir un paso ms all al escribirlo funcionalmente al escribirlo totalmente sin puntos.
Aqu si es conveniente (aunque no obligatorio) especificar el tipo de dato que recibe y que
devuelve
main = getLine >>= (putStrLn . show . fac . (read :: String -> Int))

Sin especificar el tipo de dato que se lee


main = getLine >>= (putStrLn . show . sumaCifras . (read))

El programa completo con la primera forma del main quedara de la siguiente manera

fac 0 = 1
fac n = n * fac (n-1)
main :: IO ()
main = do
n <- getLine --Le pedimos al programa que obtenga la lnea donde est el
valor de la variable x
putStrLn (show (fac (read n)))

Nota2: Recordar que Haskell, tanto online como de consola exige una correcta indentacin o
mordeo del cdigo, por lo tanto la lnea n <- getLine debe ir exactamente debajo de putStrLn
(show (fac (read n))), de lo contario va a tirar error de mordeo.

Abrimos el cuadro input:

Se nos abre el cuadro input (entrada), es ah escribimos nuestra entrada, en este caso 5

Vemos que el programa contest 120, dndonos una respuesta correcta

Introducir un nmero desde cuadro de texto input del programa


Ahora ya lemos un dato desde teclado, pero es importante saber como leer dos valores desde
teclado
Tomemos una funcin que hace una operacin cualquiera usando dos nmeros

g::Float -> Float -> Float


g n t = 2 - (7/(5**n*t))

Es una funcin que toma dos nmeros, y le aplica la frmula 2- (7 5nt) (2 7 dividido 5 a la
n por t
Pero esta funcin requiere dos argumentos, debemos aprender como leer dos argumentos desde
teclado
Ya sabemos que con n <- getLine leemos una variable llamada n y la funcin es un
InputOuput
Usando los conocimientos descriptos en las pginas anteriores con la funcin g, cambiamos la
funcin fac por g que es el nombre de la funcin nos estara quedando:

g::Float -> Float -> Float


g n t = 2 - (7/(5**n*t))
main :: IO ()
main = do
n <- getLine
putStrLn (show (g (read n)))

Tambin tirara error, porque la funcin pide dos argumentos y estamos dando uno solo.
Lo que tenemos que hacer es decir que lea la variable que llamamos t dentro del parntesis de g
que es la funcin g, escribiendo read t

El programa correctamente escrito quedara as:


g::Float -> Float -> Float
g n t = 2 - (7/(5**n*t))
main :: IO ()
main = do
n <- getLine
t <- getLine
putStrLn (show (g (read n) (read t)))

Ahora ponemos ambos valores en la caja de texto y le damos en ejecutar

El programa respondi 1.999888 que es el resultado de la operacin


Nota: Los nmeros no se pueden introducir uno separado del otro, se debe escribir en lneas
separadas, una debajo de la otra, como muestra la imagen, de lo contario va a tirar error.
Con lo explicado anteriormente, es fcil deducir como se puede programar para introducir tres o
ms nmeros desde teclado, por ejemplo, para leer variables x, y y z se usara (read x) (read
y) (read z)

Otra forma ms genrica de escribir el main es la siguiente:


main = strg <$> getLine <*> getLine >>= print where strg = flip ((flip (g .
read)) . read)

Este cdigo sirve para leer dos valores y tiene la ventaja del anterior que se pueden leer
variables de cualquier tipo, incluido listas, aunque no tupas, eso se ver ms adelante

Introducir un dato tipo cadena String desde el cuadro input del programa
Tenemos la siguiente funcin jer que lo que hace es traducir una palabra al jeringoso

je:: String->String
je [] = []
je (a:xs)= if a=='a' || a=='e' || a=='i' || a=='o' || a=='u' then
a:'p':a:je(xs) else a:je (xs)

Recordar que xs indica lista, ya que un String es una lista de caracteres, por lo tanto la lectura
en este caso tendra que ser xs, en el getline, en lugar de un carcter solo como venamos
viendo, ya que un carcter solo se usa en el caso de ser una variable.
Por lo tanto el IO quedara de la siguiente manera:

main :: IO ()
main = do
xs <- getLine
putStrLn (show (je (read xs)))

Nota: La palabra que se va a traducir a jeringoso debemos ingresarla entre comillas. Ejemplo la
palabra "Faro" traducida al jeringoso sera "Faparopo"

Como vemos, respondi de manera correcta.


Poner carteles antes de respuesta

Para hacer al programa ms amigable, podramos poner un cartel que nos informe acerca de la
respuesta simplemente colocando un putStrLn arriba de la sentencia getLine, por ejemplo

main = do
putStrLn "La palabra en jeringoso es"
xs <- getLine
putStrLn (show (je (read xs)))

Juntando todo en una lnea

putStrLn ("La palabra en jeringoso es " ++ show (je (read xs)))

Lectura de listas de enteros


Tenemos la siguiente funcin iglist que devuelve True si ambas listas son iguales y False en
caso contrario

iglist:: [Int] -> [Int] -> Bool


iglist [] [] = True
iglist [] (a) = False
iglist (a) [] = False
iglist (a:xs) (b:ys) = if a==b then iglist(xs) (ys) else False

main :: IO ()
main = do
xs <- getLine
ys <- getLine
putStrLn (show (iglist (read xs) (read ys)))

Recordar leer las dos listas con getLine y de manera separada


Como ya se aclar en la nota, debemos leer cada lnea por separado pero tambin debemos usar
parntesis recto en ambas expresiones, por ejemplo, de la siguiente forma.

Da como resultado True que es el resultado correcto.

Lo mismo ocurre si ingresamos solo un nmero, tambin debemos hacerlo entre parntesis
recto, pues indica lista, de lo contrario va a tirar error.
Ejemplo:
Tenemos las siguientes funciones, una de ellas (sumDigits) suma la cantidad de cifras de un
numero

splitDigits :: Integer -> [Integer]


splitDigits x
| x < 10 = [x]
| otherwise = (x `mod` 10) : (splitDigits (x `div` 10))

sumDigits :: [Integer] -> Integer


sumDigits [] = 0
sumDigits (x:xs) = (sum (splitDigits x)) + (sumDigits xs)

main :: IO ()
main = do
xs <- getLine
putStrLn (show (sumDigits (read xs)))

Para calcular la cantidad de cifras del nmero, por ejemplo 123 debemos ingresarlo [123] y no
123 o "123", pues en los dos ltimos casos tirara error.

La respuesta va a ser 6, que es lo correcto

Lectura de tuplas desde cuadro de texto


Lo que falta saber es como leer una tupla desde teclado. Por ejemplo, tenemos la funcin f
listada ms abajo que devuelve una tupla con la lista y la tupla que suministra el usuario
combinando la lista con la tupla de modo que por cada elemento de la primera lista crea una
tupla con el primer elemento de la segunda lista o sea "A" con ["B","C"]
Ejemplo:
Dada esta lista ["A","B","C","D"] y esta otra [["B","C"],["A","C"],["A","B","D"],
["C"]] devuelve esta lista de tupla: [("A","B"),("A","C"),("B","A"),("B","C"),
("C","A"),("C","B"),("C","D"),("D","C")]

Si somos observadores, notamos que en ejercicios anteriores cuando hacamos la lectura con
getLine y putStrLn con read no especificbamos el tipo de dato que leamos, cuando se
leen tuplas si es necesario especificar el tipo de dato que se lee, ya que Haskell no puede
inferirlo, pues no est especificado en la cabecera de la funcin.
Para especificar el tipo de dato escribimos :: y el tipo de dato. Ejemplo: Si queremos leer una
variable de tipo entero hacemos:
read a :: Int

Si quisiramos leer por ejemplo una tupla de Strings (lista de caracteres separados por comas, o
sea una cadena o String) hacemos:
read a :: [String]

Por otro lados la firma de la funcin read es read :: Read a => String -> a, Leer un
variable a implica (=>) leer un variable String y devolver otra variable
Su implantacin en Haskell es la siguiente

f :: [a] -> [[a]] -> [(a,a)]


f xs ys = [(x,y) | (x,zs) <- zip xs ys, y <- zs]

Cuyo main es el que sigue

main :: IO ()
main = do
xs <- getLine
ys <- getLine
putStrLn (show (f (read xs :: [String]) (read ys ::
[[String]])))

Va a dar [("A","B"),("A","C"),("B","A"),("B","C"),("C","A"),("C","B"),
("C","D"),("D","C")] que es el resultado correcto.

Nota: En este ejercicio, el segundo parmetro puede ser omitido, pero para brindar ms
informacin decid dejarlo

Bibliografa
Espaol
https://wiki.haskell.org/Es/Haskell_en_5_pasos

http://aprendehaskell.es/content/Tipos.html

https://es.stackoverflow.com/questions/122428/leer-2-tuplas-desde-teclado-en-haskell-
online
https://es.stackoverflow.com/questions/79874/como-transformar-dos-listas-en-una-lista-
de-tuplas-en-haskell

https://es.stackoverflow.com/questions/122428/leer-2-tuplas-desde-teclado-en-haskell-
online

Ingls
https://stackoverflow.com/questions/10264044/output-integer-to-stdout-in-haskell

S-ar putea să vă placă și