Laboratorio 3: Haskell


1. Valores y Tipos

NOTA: Establecer opción en OPTIONS/ t Print type after evaluation

Enteros y reales(int y double)
----------------------------------------------------------

Prelude> 3+2
5 :: Integer

Prelude> 3*2
6 :: Integer

Prelude> (2.8 + 4.3)
7.1 :: Double

Prelude> floor (2.3)
2 :: Integer

Prelude> 4 `div` 2
2 :: Integer

Prelude> 5 `mod` 2
1 :: Integer

Prelude> 5/2
2.5 :: Double

Booleano (bool)
--------------------------------------------------------
Prelude> 1<2 && 2<3
True :: Bool

Prelude> 1<2 || 2<1
True :: Bool

if 1<2 then 1 else 2
1 :: Integer

String (string)
----------------------------------------------------------
Prelude> "pedro"
"pedro" :: String

Prelude> "examen" ++" aprobado"
"examen aprobado" :: [Char]

Tuplas
-----------------------------------------------------------
Prelude> (1,"junio",2)
(1,"junio",2) :: (Integer,[Char],Integer)

Prelude> (1,2) == (1,2)
True :: Bool


2. Abstracciones: Funciones

Nota: Utilizar fichero aparte y cargarlo en el entorno :l test.hs

------------------------------------------------------------
Test.hs:

twice x = x*2

Interprete:

Main> twice 3
6 :: Integer

doble :: Integer -> Integer

doble x = x*2

TEST

isupper c = (c>='A') && (c<='Z')
tw = twice

INT


- tw 2

- isupper 'a'
- tw

TEST
timestamp (time, message) = message ++ (if time <12
then " a.m." else " p.m")

INT
- timestamp(8, "important meeting today ")

3. Polimorfismo (Politipos):

--------------------------------------------
first(x,y) = x
power x = x*x

power2::Integer->Integer
power2 x = x*x


abstwice x = abs(x+x)
hypotenuse (x,y)= sqrt ((x*x)+(y*y))

third_same::(a,a,a) -> a
third_same (x,y,z) = z

third_any::(a,b,c)->c
third_any (x,y,z) = z

4. Pattern Matching

----------------------------------------------------------------
negation x = if x == True then False else True

negation2 True = False
negation2 False = True



Funciones Recursivas
----------------------------------------------------------------
Recursividad de pila:

printdots 0 = ""
printdots n = "." ++ printdots (n-1)

Recursividad Acumulativa:

plus (x,0) = x
plus (x,y) = plus (x+1, y-1)

5. Ámbito (where)


test a = if a then x else "NO"
where x="SI"

6. Listas: Tipos recursivos

-----------------------------------------------------------------

Funciones:
Función : x:xs (elemento con lista)
a:[a] ->[a]


head :: [a] -> a
head (x:_) = x

last :: [a] -> a
last [x] = x
last (_:xs) = last xs

tail :: [a] -> [a]
tail (_:xs) = xs

init :: [a] -> [a]
init [x] = []
init (x:xs) = x : init xs

null :: [a] -> Bool
null [] = True
null (_:_) = False

(++) :: [a] -> [a] -> [a]
[] ++ ys = ys
(x:xs) ++ ys = x : (xs ++ ys)

Pruebas:


[1,2,3]
['1','2','3']
"123"
1:[2,3,4]
'a':"abc"
[1]++[2,3]
"1"++"23"
head [1,2,3]
tail [1,2,3]



7. Listas y recursión

--------------------------------------------------------------

Recursión de pila en listas
-------------------------------
fun template nil
= valor final
| template (front::rest)

sumlist :: [Integer] -> Integer
sumlist [] = 0
sumlist (front:rest)= front + sumlist rest



Recursión acumulativa
-------------------------------
fun aux (nil, accumulator)
= accumulator
| aux (front::rest), accumulator)
= aux(rest,(hacer algo con front y accumulator))
fun main nil
= condicion de fin o raise excepcion
| main any = aux ( any, (valor inicial de accumulator))



xsum ([], total) = total
xsum (front:rest, total) = xsum (rest, front+total)

sumlist2 :: [Integer] -> Integer
sumlist2 [] = 0
sumlist2 (any) = xsum(any,0)




Funciones polimórficas recursivas

long:: [a] -> Integer
long ([]) = 0
long (front:rest) = 1 + long rest

Ejercicio 1. Escribir una función recursiva de pila que sume todos los numeros menores de 3 que aparezcan en una lista de enteros

Ejercicio 2. Escribir una función recursiva acumulativa que calcule el máximo elemento de la lista.

Ejercicio 3.Crear una función que convierta una cadena ("1234") a un entero (1234). Crear una función que convierta un entero a una cadena.

Ejercicio 4. Crear una función listar_enteros (n,lista) que devuelva una lista con los enteros comprendidos entre 0 y n.
Ejercicio 5. Crear una función listar_entre(inicio,fin,lista,acc) que devuelva una lista formada por los enteros entre inicio y fin.
Ejercicio 6. Modificar el ejercicio 5 para que solo muestre los múltiplos de 2.

 


8. Tipos de Datos

------------------------------------------------------------

Dado el esquema:

datatype nombre
= valor1
|...
| valorN

datatype nombre_constructor of tipo

Probar estos ejemplos:


data Color = Red | Green | Blue

data Grade = A | B | C | D | F

data Color2 = Rgb (Integer,Integer) deriving (Eq, Show)


Rgb(1,2);


Ejercicio 7. Crear el tipo de datos coche, cuyos tipos de datos serán la marca y el precio. Hacer una función que acepte dos coches y nos diga cual es más caro.


Parametrizando tipos:

data Car a= Coche (a,Integer) deriving (Eq,Show)

Main> Coche("a",100)
Coche ("a",100) :: Car [Char]
Main> Coche(2,100)
Coche (2,100) :: Car Integer



Tipos de datos recursivos
--------------------------------------------------

Lista simple:

data List a = Cons a (List a)
| Nil
- Cons(1,Nil)
- Cons(1,Cons(2,Nil))

Arboles:
data Arbol a = Planta ((Arbol a),a, (Arbol a)) | Anil deriving (Eq, Show)


tree2list Anil = []
tree2list (Planta(a,b,c)) = tree2list a++[b]++tree2list c

Ejercicio 8. Probar la función con un arbol creado por nosotros:
Ejemplo:
3
4 5
6 7 8 9
Ejercicio 9. Escribir una función que calcule el máximo elemento de un arbol.

Ejercicio 10. Escribir una función que nos indique si un elemento pertenece a un arbol.

Ejercicio 11. Escribir una función que calcule la suma de los elementos de un arbol.

Ejercicio 12. Escribir una función que calcule la altura de un árbol.

9. Higher Order Functions

---------------------------------------------------
getnth _ [] = 0
getnth 1 (x:xs) = x
getnth n (x:xs) = getnth (n-1) xs

segundo = getnth 2
quinto = getnth 5




Funciones de alto nivel en listas (map):


map f [] = []
map f (x:xs) = f x:map f xs


Ejercicio 13. Implementar la función power (n,b) que eleva n a b y utilizar funciones de alto nivel para calcular la función cubo.


Ejercicio 14.
Probar la función map con diferentes funciones: incrementar en uno, multiplicar por 2, ...
Crear la función de alto nivel map_inc que parametrice parcialmente map.

Ejercicio 15.
Utilizando la solución del ejercicio 5, modificarlo para que la funcion acepte una función como parametro.
Queremos que se aplique esta función sobre cada uno de los elementos entre inicio y fin que se almacenarán en la lista final.

Pistas: Esta función aceptará un entero y devolverá un entero. Ejemplo : fun incr x = x+1; Para pasarla como parámetro escribiremos (nombrefuncion:int->int).


Ejercicio 16. Implementar una función de alto nivel llamada filter, que acepte dos parámetros , el primero será una función con un parámetro polimórfico que devolverá un valor booleano, el segundo será una lista polimórfica. La función filter devolverá una lista formada por los elementos de la lista original cuyos elementos cumplan el predicado establecido por la función.


-filter (islessthan 3) [1,7,2,9,67,3];
val it = [1,2]:int list;

Ejercicio 17. Implementar las funciones filter y map con listas intensionales.

Ejercicio 18. c) Implementa las funciones concatenar_listas, longitud, y sum_list parametrizando parcialmente la función foldr.

foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)

Ejercicio 19. ¿ que hacen las funciones siguientes ? Explicalas con ejemplos. Muestra un ejemplo de parametrización parcial sobre alguna de ellas.

take :: Int -> [a] -> [a]
take n _ | n <= 0 = []
take _ [] = []
take n (x:xs) = x : take (n-1) xs

drop :: Int -> [a] -> [a]
drop n xs | n <= 0 = xs
drop _ [] = []
drop n (_:xs) = drop (n-1) xs

takeWhile :: (a -> Bool) -> [a] -> [a]
takeWhile p [] = []
takeWhile p (x:xs)
| p x = x : takeWhile p xs
| otherwise = []

dropWhile :: (a -> Bool) -> [a] -> [a]
dropWhile p [] = []
dropWhile p xs@(x:xs')
| p x = dropWhile p xs'
| otherwise = xs

10. Lazy Evaluation


falla(x,y) = if y == 0 then 1 else x
falla(1/0,0) ??????

numsFrom n = n : numsFrom (n+1)
squares = map (^2) (numsfrom 0)

take :: Int -> [a] -> [a]
take n _ | n <= 0 = []
take _ [] = []
take n (x:xs) = x : take (n-1) xs

take 5 squares => [0,1,4,9,16]

Ejercicio 20. Problema TurboRISK


Se trata de modelar un "prototipo ligero" del juego del TurboRisk en Haskell, adaptándolo al paradigma funcional. Los territorios y continentes pueden estar prefijados. Reducir el problema considerablemente a dos funciones como placement y attack, e implementar como ejemplo alguna función sobre Territorios como TBorder, TisFront. Utilizar funciones y listas.

Es necesario disponer de al menos dos jugadores sencillos de ejemplo y código de Test que pruebe la ejecución de uno o varios turnos del juego.Que muestre la lista resultado de pasar uno o varios turnos.

Ejercicio 21. (OPCIONAL) Escribir una definición intensional de lista que incluya las piezas negras de un tablero de ajedrez.
Pista: ord ‘A’ = 65
even 2 = True