Quiere recorrer toda la estructura de datos y cambiar algunos elementos aquí y allá. Esto generalmente se realiza mediante una función que toma la estructura de datos como parámetro y devuelve la nueva versión modificada de la estructura.
Para cada caso de entrada, esta función define cómo se verá el nuevo valor que se devuelve como .
La función básica que modifica una Tree
(que es sólo una lista de valores DataA
) probablemente sólo debe devolver una nueva lista de valores modificados. Si nos remitimos aquellos modificaciones de los valores a una función modifyA
, la función principal modificación se ve así:
-- # function to change a |Tree|
mutate :: Tree -> Tree
mutate as = map mutateA as
-- # (The |map| function applies the |mutateA| function to every
-- # element of |as|, creating a list of all the return values)
Ahora la función mutateA
necesita ser definida para cambiar todas las posibles DataA
valores y mejor es acompañado por una función mutateB
que maneja los valores DataB
.
Estas funciones se ven en los diferentes casos posibles de valores y devuelven los nuevos valores apropiados:
-- # function to change |DataA| items
mutateA :: DataA -> DataA
-- # A |DataA1| is a |DataA1| with modified values
mutateA (DataA1 bs) = DataA1 (map mutateB bs)
-- # A |DataA3| is a |DataA3| with modified values
mutateA (DataA3 s as) = DataA3 s (map mutateA as)
-- # In the remaining case(s) the value stays the same
mutateA d = d
-- # function to change |DataB| items
mutateB :: DataB -> DataB
mutateB (DataB1 as) = DataB1 (map mutateA as)
mutateB (DataB3 s bs) = DataB3 s (map mutateB bs)
-- # Here comes a real change
mutateB (DataB2 _) = DataB2 "foo"
esta manera para cada elemento en el árbol de un nuevo elemento se calcula, en el que todos los DataB2
valores en cualquier parte en el árbol son reemplazados por "foo".
Es relativamente prolijo porque tiene cinco casos diferentes que contienen una lista de valores que debe recorrer, pero que no es específico de Haskell. En un idioma imperativo, normalmente tendría cinco bucles for en lugar de las cinco llamadas al map
.
Tal vez podría simplificar su estructura de datos para reducir esta "sobrecarga".Este , por supuesto, depende de su caso de uso real, pero tal vez, por ejemplo, usted no necesita los casos Data2
: ¿Hay una diferencia entre DataA2 "abc"
y DataA3 "abc" []
?
Gracias. Esto es lo que estaba buscando. Para que esto funcione, tuve que importar Data.Generics – Chris
¡Tienes razón, mi mal! Solucionado mi respuesta. Gracias. – Martijn
Brillante. Me alegra que alguien aquí sepa cómo hacer que SYB funcione. +1 –