[Prueba 2017] Ejercicios 4, 7 y 10

[Prueba 2017] Ejercicios 4, 7 y 10

de Eliana Rosselli Orrico -
Número de respuestas: 1

Buenas,

Haciendo la prueba de 2017 me surgieron algunas dudas con respecto a los ejercicios 4, 7 y 10.

4. Dada la siguiente definición:
foo f a = map (f a)
¿Cuál de las siguientes afirmaciones no es correcta?
(a) El tipo es foo :: (a → b → c) → a → [b ] → [c ]
(b) foo (||) False ≡ id
(c) sum ◦ foo const 1 ≡ length
(d) foo ($) ≡ map

No me queda claro por qué la b) no es correcta (es porque los tipos no coinciden?). Tampoco me queda claro por qué la d) sí lo es.


7. Dado el siguiente fragmento:
mon x = monaux x >> print x
¿Cual de las siguientes afirmaciones es correcta?
(a) Si monaux tiene tipo monaux :: Monad m ⇒ a → m () el tipo de
mon es mon :: (Show a, Monad m) ⇒ a → m ()
(b) No importa cual sea la definicion de monaux , si su tipo es correcto
la aplicacion (mon 9) siempre termina imprimiendo 9
(c) Si monaux tiene tipo monaux :: Monad m ⇒ Int → m Int el codigo
de mon no compila
(d) Si (monaux x ) diverge entonces (mon x ) diverge

No entiendo por qué la a) es incorrecta y por qué la d) es correcta. El operador >> necesariamente evalúa ambos argumentos?


10. Dadas las siguientes definiciones:
data Arbol a = Vacio | Nodo (Arbol a) a (Arbol a)
genera = fst $ generaAux 0
where generaAux n = let (l, n0) = generaAux (n + 1)
                        (r , n00) = generaAux n0
                    in (Nodo l n r , n00)
recorreL (Nodo l x ) = x : recorreL l
recorreL Vacio = [ ]
recorreR (Nodo x r ) = x : recorreR r
recorreR Vacio = [ ]
recorre (Nodo l x r ) = recorre l ++ [x ] ++ recorre r
recorre Vacio = [ ]

Entiendo que la expresión de la parte b) (take 5 ◦ tail ◦ recorreR $ genera) diverge, pero no entiendo entonces por qué no lo hace d) (head $ zip (recorreL genera) (recorreR genera)).

Muchas gracias y saludos!

En respuesta a Eliana Rosselli Orrico

Re: [Prueba 2017] Ejercicios 4, 7 y 10

de Marcos Viera - InCo -
4.
b.
La función `id` tiene tipo:
 
id :: a -> a

Por lo que la puedo aplicar a valores de cualquier tipo. Puedo hacer por ejemplo `id 4`.
En cambio `foo (||) False` tiene tipo
[Bool] -> [Bool]
.

d.
 
foo ($) f xs = map (($) f) xs

Como `($)` es el operador de aplicación, hacer `($) f` equivale a `f`.
Entonces:
 
foo ($) f xs = map f xs


7.
a.
El tipo de `print` es:
 
print :: Show a => a -> IO ()

retornando acciones en la mónada `IO`. Entonces no se puede decir que `mon` es polimórfico con respecto a la mónada `m`.

b. El bind de mónadas obliga a que exista una secuencia en la evaluación de las computaciones, dado que la primera computación debe generar algo para que con eso se construya la segunda computación. Si la primera computación no llega a generar nada, entonces no se construye la segunda.

10.
La función `genera` produce un árbol que tiene infinitos nodos hacia la izquierda, por lo que si intento ir hacia la derecha quedo en una computación divergente.
El tema con la llamada `(head $ zip (recorreL genera) (recorreR genera))` es que el árbol tiene un nodo raíz que tiene el valor `0`, y tanto `recorreL` como `recorreR` colocan el valor del nodo raíz al principio de sus respectivas listas antes de seguir recorriendo. Por lo tanto al avanzar un paso en el `zip` para ambas listas se obtiene `(0,0)` en la cabeza de la lista resultante, que es todo lo que se necesita para evaluar `head`.