Tabla de Contenidos

Clase 4

Plan para hoy

Soluciones en la Wiki del Práctico 8: estado

Clase

Nos proponemos hacer un programa funcional que cuente la frecuencia de las ocurrencias de palabras.

frecuencia :: [Palabra] -> [(Palabra,Int)]
Main> frecuencia ["hola","que","hola"]
[("hola",2),("que",1)]

Donde Palabra es un sinónimo de tipo, en este caso de un String, y sirve para mejorar la legibilidad del código.

type Palabra = String

Para hacer más fácil el uso de esta función tomamos de Haskell The Craft of Functional Programming por Simon Thompson, la definción de una función que parte una cadena en palabras.

espacio :: [Char]
espacio = ['\n','\t',' ']

esta :: Eq a => a -> [a] -> Bool
-- Definirlo!

-- Tambien podemos escribirlo como tomaPalabra :: [Char] -> [Char]
tomaPalabra :: String -> String
tomaPalabra [] = []
tomaPalabra (x:xs)      | esta x espacio = []
                        | otherwise      = x : tomaPalabra xs


tiraPalabra :: String -> String
tiraPalabra [] = []
tiraPalabra (x:xs)      | esta x espacio = x:xs
                        | otherwise      = tiraPalabra xs


tiraEspacio :: String -> String
tiraEspacio [] = []
tiraEspacio (x:xs)      | esta x espacio = tiraEspacio xs
                        | otherwise      = x:xs

-- Declaracion de tipos
type Palabra = String

partirPalabras :: String -> [Palabra]
partirPalabras st = partirPalabras' (tiraEspacio st)

partirPalabras' :: String -> [Palabra]
partirPalabras' [] = []
partirPalabras' st = (tomaPalabra st) : partirPalabras' (tiraEspacio (tiraPalabra st))

Todas estas definciones las metemos en el archivo frec.hs.

Notamos:

Una vez definida la función esta podemos probar las funciones.

Main> tomaPalabra "Despues de tres dias"
"Despues"
Main> tiraEspacio "Despues de tres dias"
"Despues de tres dias"
Main> tiraEspacio "           Despues de tres dias"
"Despues de tres dias"
Main> tiraPalabra "           Despues de tres dias"
"           Despues de tres dias"
Main> tiraPalabra "Despues de tres dias"
" de tres dias"
Main> partirPalabras "hola"
["hola"]
Main> partirPalabras "hola que tal"
["hola","que","tal"]
Main> partirPalabras "              hola que            tal              "
["hola","que","tal"]

Finalmente tenemos que definir la funcion que computa la frecuencia

frecuencia :: [Palabra] -> [(Palabra,Int)]

Por ejemplo

Main> frecuencia ["hola","que","hola"]
[("hola",2),("que",1)]
Main> frecuencia (partirPalabras "Despues de tres dias Nebel decidio aclarar de una vez ese estado de osas, y aprovecho para ello un momento en que Lidia no estaba.")
[("estaba.",1),("no",1),("Lidia",1),("que",1),("en",1),("momento",1),("un",1),("ello",1),("para",1),("aprovecho",1),("y",1),("osas,",1),("de",3),("estado",1),("ese",1),("vez",1),("una",1),("aclarar",1),("decidio",1),("Nebel",1),("dias",1),("tres",1),("Despues",1)]

Para probar ejemplos más largos podemos agregar una función que dado el nombre de un archivo, devuelve un String con ese archivo (tomado de EasyIO.hs del curso Introductory Functional Programming for Physics Students 8-O)
Este código debe estar al inicio del script.

import IOExts

leeArchivo :: String -> String
leeArchivo nombre = unsafePerformIO$ readFile nombre

Para obtener textos largos e interesantes tenemos el Proyecto Gutemberg-Español donde hay muchos libros que ya no tienen derecho de copia.
Por ejemplo están Cuentos de Amor de Locura y de Muerte de Horacio Quiroga y El Gaucho Martín Fierro de José Hernandez.

Hay que tener cuidado con la codificación pues no todas funcionan.
Por ejemplo UTF8 es una codificación posible: Martín Fierro en UTF8, y calculamos la lista de frecuencias.

Main> frecuencia (partirPalabras (leeArchivo "14765-utf8.txt"))

Ejercicios

Puede ser útil definir la función agregarOcurrencia :: Palabra → [(Palabra,Int)] → [(Palabra,Int)] que dada una palabra y una lista de frecuencias, suma esta palabra a la lista de frecuencias.
Por ejemplo:

agregarOcurrencia "que" [("hola",2), ("que",1)] = [("hola",2), ("que",2)]
agregarOcurrencia "hola" [] = [("hola",1)]
agregarOcurrencia "que" [("hola",2)] = [("hola",2), ("que",1)]

?Como será el parcialito 3 en máquina?