En programación informática , un tipo de dato recursivo es aquel cuya definición contiene valores del mismo tipo. También se le conoce como tipo de dato definido recursivamente , inductivamente o inductivo . Los datos de tipos recursivos suelen representarse como grafos dirigidos .
Una aplicación importante de la recursión en informática reside en la definición de estructuras de datos dinámicas, como listas y árboles. Las estructuras de datos recursivas pueden crecer dinámicamente hasta alcanzar un tamaño arbitrariamente grande en respuesta a las necesidades de ejecución; en cambio, el tamaño de un array estático debe definirse en tiempo de compilación.
En ocasiones, el término "tipo de dato inductivo" se utiliza para referirse a tipos de datos algebraicos que no son necesariamente recursivos.
Ejemplo
Un ejemplo es el tipo de lista , en Haskell :
Lista de datos a = Nil | Cons a ( Lista a )Esto indica que una lista de 'a's' es una lista vacía o una celda cons que contiene una 'a' (la "cabeza" de la lista) y otra lista (la "cola").
Otro ejemplo es un tipo enlazado simple similar en Java :
clase pública LinkedList < E > { privado E valor ; privado LinkedList < E > siguiente ;// constructor y métodos... }Esto indica que la lista no vacía de tipo Econtiene un miembro de datos de tipo Ey una referencia a otro objeto List para el resto de la lista (o una referencia nula para indicar que este es el final de la lista).
Tipos de datos mutuamente recursivos
Los tipos de datos también pueden definirse mediante recursión mutua . El ejemplo básico más importante de esto es un árbol , que puede definirse de forma recursiva mutua en términos de un bosque (una lista de árboles). Simbólicamente:
f: [t[1], ..., t[k]] t: vfUn bosque f consiste en una lista de árboles, mientras que un árbol t consiste en un par formado por un valor v y un bosque f (sus descendientes). Esta definición es elegante y fácil de usar de forma abstracta (por ejemplo, al demostrar teoremas sobre propiedades de árboles), ya que expresa un árbol en términos sencillos: una lista de un tipo y un par de dos tipos.
Esta definición mutuamente recursiva se puede convertir en una definición recursiva simple insertando en línea la definición de un bosque:
t: v [t[1], ..., t[k]]Un árbol t consta de un par formado por un valor v y una lista de árboles (sus hijos). Esta definición es más compacta, pero algo más compleja: un árbol consta de un par de un tipo y una lista de otro, que requieren ser desentrañados para demostrar resultados sobre él.
En Standard ML , los tipos de datos de árbol y bosque se pueden definir recursivamente de forma mutua como sigue, permitiendo árboles vacíos: [ 1 ]
tipo de datos 'un árbol = Vacío | Nodo de 'un * 'un bosque y 'un bosque = Nulo | Cons de 'un árbol * 'un bosqueEn Haskell, los tipos de datos de árbol y bosque se pueden definir de forma similar:
Árbol de datos a = Vacío | Nodo ( a , Bosque a )Datos Bosque a = Nulo | Cons ( Árbol a ) ( Bosque a )Teoría
En teoría de tipos , un tipo recursivo tiene la forma general μα . T donde la variable de tipo α puede aparecer en el tipo T y representa el tipo completo en sí mismo.
Por ejemplo, los números naturales (véase la aritmética de Peano ) pueden definirse mediante el tipo de datos de Haskell:
datos Nat = Cero | Succ NatEn teoría de tipos, diríamos:donde los dos brazos del tipo suma representan los constructores de datos Zero y Succ. Zero no toma argumentos (por lo tanto, está representado por el tipo de unidad ) y Succ toma otro Nat (por lo tanto, otro elemento de).
Existen dos formas de tipos recursivos: los llamados tipos isorrecursivos y los tipos equirrecursivos. La diferencia entre ambas radica en cómo se introducen y eliminan los términos de un tipo recursivo.
tipos isorecursivos
Con los tipos isorrecursivos, el tipo recursivoy su expansión (o despliegue )(donde la notaciónindica que todas las instancias de Z se reemplazan con Y en X) son tipos distintos (y disjuntos) con construcciones de términos especiales, generalmente llamadas roll y unroll , que forman un isomorfismo entre ellos. Para ser precisos:yy estas dos son funciones inversas .
tipos equirrecursivos
Bajo reglas equirrecursivas, un tipo recursivoy su desarrolloson iguales ; es decir, se entiende que esas dos expresiones de tipo denotan el mismo tipo. De hecho, la mayoría de las teorías de tipos equirrecursivos van más allá y especifican esencialmente que dos expresiones de tipo cualesquiera con la misma "expansión infinita" son equivalentes. Como resultado de estas reglas, los tipos equirrecursivos contribuyen significativamente más a la complejidad de un sistema de tipos que los tipos isorecursivos. Los problemas algorítmicos, como la verificación de tipos y la inferencia de tipos, también son más difíciles para los tipos equirrecursivos. Dado que la comparación directa no tiene sentido en un tipo equirrecursivo, estos pueden convertirse a una forma canónica en tiempo O(n log n), que puede compararse fácilmente. [ 2 ]
Los tipos isorrecursivos capturan la forma de las definiciones de tipos autorreferenciales (o mutuamente referenciales) que se observan en los lenguajes de programación orientados a objetos nominales , y también surgen en la semántica de la teoría de tipos de objetos y clases . En los lenguajes de programación funcional, los tipos isorrecursivos (bajo la apariencia de tipos de datos) también son comunes. [ 3 ]
Sinónimos de tipo recursivo
En TypeScript , la recursión está permitida en los alias de tipo. [ 4 ]
Véase también
Referencias
- ↑ Harper 1998 .
- ↑ "La numeración importa: formas canónicas de primer orden para tipos recursivos de segundo orden". CiteSeerX 10.1.1.4.2276 .
- ↑ Revisión del subtipado isorrecursivo | Actas de la ACM sobre lenguajes de programación
- ↑ (Más) Alias de tipo recursivos - Anuncio de TypeScript 3.7 - TypeScript
Fuentes
- Harper, Robert (1998), Declaraciones de tipos de datos , archivado del original el 1 de octubre de 1999
- Tipos de datos
- teoría de tipos