una promedio potencia listas lista infinitas imprimir eliminar elemento ciclos aprende haskell

promedio - Haskell: Duplica cada 2do elemento en la lista



potencia en haskell (5)

Acabo de empezar a usar Haskell y quería escribir una función que, dada una lista, devuelve una lista en la que cada segundo elemento se ha duplicado.

Hasta ahora he llegado con esto:

double_2nd :: [Int] -> [Int] double_2nd [] = [] double_2nd (x:xs) = x : (2 * head xs) : double_2nd (tail xs)

Lo cual funciona pero me preguntaba cómo escribirían esa función. ¿Hay una forma más común / mejor o esto parece correcto?


Eso no está mal, modulo las correcciones sugeridas. Una vez que se familiarice con la biblioteca base, es probable que evite la recursión explícita en favor de algunas funciones de nivel superior; por ejemplo, puede crear una lista de funciones donde todas las demás son *2 y aplicar (zip) esa lista de funciones a tu lista de números:

double = zipWith ($) (cycle [id,(*2)])


Para listas impares o double_2nd [x] siempre puedes agregar

double_2nd (x:xs) | length xs == 0 = [x] | otherwise = x : (2 * head xs) : double_2nd (tail xs)

Gracias.


Pruébalo en una lista de longitud impar:

Prelude> double_2nd [1] [1,*** Exception: Prelude.head: empty list

Y puedes ver el problema con tu código. La ''cabeza'' y la ''cola'' nunca son una buena idea.


Puede evitar excepciones de "lista vacía" con alguna coincidencia de patrón inteligente.

double2nd (x:y:xs) = x : 2 * y : double2nd xs double2nd a = a

esto es simplemente sintaxis de azúcar para el siguiente

double2nd xs = case xs of x:y:xs -> x : 2 * y : double2nd xs a -> a

la coincidencia del patrón se realiza en orden, por lo que xs se comparará con el patrón x:y:xs primero. Entonces, si eso falla, el patrón catch-all a tendrá éxito.


Un poco de nigromancia, pero creo que este método funcionó muy bien para mí y quiero compartirlo:

double2nd n = zipWith (*) n (cycle [1,2])

zipWith toma una función y luego la aplica a los elementos coincidentes en dos listas (primer elemento al primer elemento, segundo elemento al segundo elemento, etc.). La función es la multiplicación, y la lista comprimida es un ciclo sin fin de 1s y 2s. zipWith (y todas las variantes de zip) se detiene al final de la lista más corta.