Buenas, paso a dejar el enunciado tomado el 21 de diciembre con mi resolución.
Me saqué un 9 pero no se cual punto estaba mal.
Parte objetos:
1)a) Hay un mal uso de la herencia, debido a que Cultivo no tiene ningun atributo ni logica compartida que las clases hijas necesiten.
1)b) Este punto hacia referencia a los IF para determinar el tipo de campo.
Hay un error, ya que "if(hectareas > 2000)" no tiene ninguno uso. Si la cantidad no es menor a 100 ni esta dentro del rango de 100 a 2000, obligatoriamente es mayor.
1)c) Hay buen polimorfismo debido a que los 3 cultivos conocen el método "retencion()" y saben resolverlo de una manera particular.
1)d) Mal uso. La lógica de saber la retención en base al tamaño del campo se debería abstraer en un método en la clase Cultivo, ya que las 3 clases hijas lo necesitan y lo usan de igual forma.
2)
Abstract Class Cultivo{
var retencion;
var cantidadHectareas;
method retencionBase(){
return self.retencion
}
method retencion(){
return self.retencionBase();
}
method cantidadHectareas(){
return self.cantidadHectareas;
}
method retencionPorTamañoDeCampo(){
if(cantidadHectareas <100){
return 0.5;
}
if(cantidadHectareas.between(100,2000){
return 1.5
}
return 2.5:
}
}
Class Trigo inherits Cultivo{
@Override
method retencion(){
return (super() + self.retencionPorTamañoDeCampo()) * self.cantidadHectareas();
}
@Override
method retencionBase(){
if(cantidadHectareas.even()){
return 0.5
}
return 0.3;
}
}
Class Soja inherits Cultivo{
@Override
method retencionBase(){
return 1000;
}
@Override
method retencion(){
return super() * self.retencionPorTamañoDeCampo();
}
}
Class Maiz inherits Cultivo{
var cantidadHectareasSembradas
var cantidadHectareasPerdidas
@Override
method retencionBase(){
if(cantidadHectareasPerdidas >100){
return 0;
}
return 1.10;
}
@Override
method retencion(){
return (super() + self.retencionPorTamañoDeCampo()) * cantidadHectareasSembradas:
}
}
Aclaración: Elegi usar una clase abstracta porque necesito implementar código compartido (retencionPorTamañoDeCampo()) como así también establecer que se deben implementar ciertos metodos (retencion() y retencionBase())
Parte Lógico:
1) tieneProblemas/1 es un predicado que indica si una persona tiene problemas con el alcohol, esto se cumple si todas las bebidas que toma tienen alcohol.
tieneProblemas(juan) es falso ya que juan toma coca cola.
2)a) Verdadero, porque se esta enfocando en el "COMO" hay que hacer y no en el "QUE" hay que hacer. Hay mucho detalle algoritmico en la solucion planteada.
2)b) Falso. Si bien contempla todos los tipos de bebida alcohólica existente, no los trata de forma polimorfica ya que crea una lista para cada tipo de bebida. Si se incluyese una nueva bebida, se debería reformular todo el predicado.
3)
tieneProblemas(Persona):-
esBebedora(Persona),
forall(toma(Persona,Bebida), esAlcoholica(Bebida)).
esBebedora(Persona):-
toma(Persona,_).
esAlcoholica(vino(_,_)).
esAlcoholica(cerveza(_,_,Alcohol)):-
Alcohol > 0.
Nota: esBebedora es un predicado que liga la variable persona, para que tieneProblemas/1 sea inversible previo ingreso al forall
Parte lógico:
1)a) Verdadero, implementar esa funcion agregarIngrediente sería:
agregarIngrediente :: Combo -> Ingrediente -> [Ingrediente]
agregarIngrediente (Combo Ingredientes _) NuevoIngrediente = Ingredientes : NuevoIngrediente
Pero se podria reformular de la siguiente manera para poder tratar a todas estas funciones de igual forma y que retornen el combo completo, luego de ser modificado.
agregarIngrediente :: Ingrediente -> Combo -> Combo
agregarIngrediente NuevoIngrediente (Combo Ingredientes Bebida) = Combo (Ingredientes : NuevoIngrediente) Bebida
1)b) Falso. Haskell no tiene efecto, por lo que aplicar las funcioens por separado no "combina" su funcionalidad. Para que eso suceda se debe hacer (Utilizando mi reformulacion del punto 1):
(agregarIngrediente "panceta).(cambiarBebida "soda") combo
1)c) Verdadero, por lo explicado anteriormente en el punto 1)a)
2)
agregarIngrediente :: Ingrediente -> Combo -> Combo
agregarIngrediente NuevoIngrediente (Combo Ingredientes Bebida) = Combo (Ingredientes : NuevoIngrediente) Bebida
cambiarBebida :: String -> Combo -> Combo
cambiarBebida NuevaBebida (Combo Ing Bebida) = Combo Ing NuevaBebida
(agregarIngrediente "panceta).(cambiarBebida "soda") combo
3)a)
comboBasico = Combo ["queso"] "coca"
3)b)
type Modificacion = Combo -> Combo
agregarIngrediente :: Ingrediente -> Modificacion
agregarIngrediente NuevoIngrediente (Combo Ingredientes Bebida) = Combo (Ingredientes : NuevoIngrediente) Bebida
cambiarBebida :: Bebida -> Modificacion
cambiarBebida NuevaBebida (Combo Ing Bebida) = Combo Ing NuevaBebida
aplicarModificaciones :: [Modificacion] -> Combo -> Combo
aplicarModificaciones modificaciones combo = foldl1 ($ combo) modificaciones
4)
Orden superior: La función FOLDL1 es de orden superior, ya que toma como parámetro una función.
Aplicación parcial: Para poder tener una lista de modificaciones, se le debe aplicar parcialmente una bebida o un ingrediente, para que todas sean del tipo Modificacion.
Tipos propios: Tuve que definir un tipo Modificacion para simplificar y ayudar a la expresividad de la función.
Saludos!