De hecho, puede darle al árbol un parámetro de tipo, como en el ejemplo de Alexander Poluektov. ¡Suficientemente simple! Pero ¿por qué detenerse allí? Podemos divertirnos un poco más que eso. En lugar de solo una estructura recursiva con datos polimórficos , puede hacer que la estructura sea polimórfica en la recursión misma!
En primer lugar, abstraiga las referencias del árbol a sí mismo, de la misma manera que abstraer las referencias a Int
, reemplazando las referencias recursivas con un nuevo parámetro t
. Eso nos deja con esta estructura de datos bastante vagos:
data TNode t a = Empty
| Leaf a
| Node (t a) a (t a)
deriving (Eq, Ord, Show, Read)
Esto ha sido renombrada como TNode
aquí porque no es realmente un árbol más; solo un tipo de datos simple. Ahora, para recuperar la recursividad original y crear un árbol, torcemos TNode
alrededor y alimentar a sí mismo:
newtype Tree a = Tree (TNode Tree a) deriving (Eq, Ord, Show, Read)
Ahora podemos utilizar este Tree
de forma recursiva, aunque por desgracia a costa de cierta verborrea adicional, así:
Tree (Node (Tree Empty) 5 (Tree (Leaf 2)))
Entonces, ¿qué nos da esto, además de escribir extra, usted pregunta? Simplemente que hemos separado la estructura del árbol fundamental tanto de los datos que contiene como del método por el cual se construyen y procesan los datos, lo que nos permite escribir funciones más genéricas para tratar con un aspecto u otro.
Por ejemplo, podemos decorar árboles con datos adicionales o empalmar materiales adicionales en el árbol, sin afectar las funciones de árbol genéricas.Decimos que queríamos dar un nombre a cada pieza del árbol:
newtype NameTree a = NameTree (String, TNode NameTree a) deriving (Eq, Ord, Show, Read)
Por otro lado, podemos escribir genérica lógica recorrido del árbol:
toList f t = toList' f (f t) []
where toList' f (Node t1 x t2) xs = toList' f (f t1) (x : toList' f (f t2) xs)
toList' f (Leaf x) xs = x:xs
toList' _ Empty xs = xs
Dada una función para extraer la corriente TNode
de un árbol recursivo, podemos utilizar esto en cualquier estructura:
treeToList = toList (\(Tree t) -> t)
nameTreeToList = toList (\(NameTree (_, t)) -> t)
por supuesto, esto probablemente va mucho más allá de lo que está buscando hacer, pero es un buen sabor de lo mucho polimorfismo y el código genérico Haskell permite (más aún, fomenta) que un programador cree.