La programación funcional total (también conocida como programación funcional fuerte , [1] en contraste con la programación funcional ordinaria o débil ) es un paradigma de programación que restringe la gama de programas a aquellos que probablemente estén finalizando . [2]
La rescisión está garantizada por las siguientes restricciones:
Estas restricciones significan que la programación funcional total no es completa en Turing . Sin embargo, el conjunto de algoritmos que se pueden utilizar sigue siendo enorme. Por ejemplo, cualquier algoritmo para el cual se pueda calcular un límite superior asintótico (mediante un programa que solo usa la recursión de Walther) se puede transformar trivialmente en una función terminante demostrable usando el límite superior como un argumento adicional decrementado en cada iteración o recursión. .
Por ejemplo, no se demuestra trivialmente que la ordenación rápida sea recursiva subestructural, pero solo recurre a una profundidad máxima de la longitud del vector (complejidad temporal en el peor de los casos O ( n 2 )). Una implementación de clasificación rápida en listas (que sería rechazada por un verificador recursivo subestructural) es, usando Haskell :
importar Data.List ( partición ) qsort [] = [] qsort [ a ] = [ a ] qsort ( a : como ) = let ( menor , mayor ) = partición ( < a ) como en qsort menor ++ [ a ] ++ qsort mayor
Para hacerlo recursivo subestructural usando la longitud del vector como límite, podríamos hacer:
importar Data.List ( partición ) qsort x = qsortSub x x -- caso mínimo qsortSub [] as = as -- muestra terminación -- casos qsort estándar qsortSub ( l : ls ) [] = [] -- no recursivo, por lo que se acepta qsortSub ( l : ls ) [ a ] = [ a ] - no recursivo, por lo que se acepta qsortSub ( l : ls ) ( a : as ) = let ( lesser , mayor ) = partición ( < a ) as -- recursivo, pero recurrente en ls, que es una subestructura de -- su primera entrada. en qsortSub ls menor ++ [ a ] ++ qsortSub ls mayor
Algunas clases de algoritmos no tienen un límite superior teórico, pero sí un límite superior práctico (por ejemplo, algunos algoritmos basados en heurísticas pueden programarse para "darse por vencidos" después de tantas recursiones, asegurando también la terminación).
Otro resultado de la programación funcional total es que tanto la evaluación estricta como la evaluación perezosa dan como resultado el mismo comportamiento, en principio; sin embargo, uno u otro puede seguir siendo preferible (o incluso necesario) por motivos de rendimiento. [4]
En la programación funcional total se hace una distinción entre datos y codatos : los primeros son finitos , mientras que los segundos son potencialmente infinitos. Estas estructuras de datos potencialmente infinitas se utilizan para aplicaciones como E/S . El uso de codata implica el uso de operaciones como corecursion . Sin embargo, es posible realizar E/S en un lenguaje de programación totalmente funcional (con tipos dependientes ) también sin codata. [5]
Tanto Epigram como Charity podrían considerarse lenguajes de programación totalmente funcionales, aunque no funcionan de la manera que Turner especifica en su artículo. También podría serlo la programación directa en el Sistema F simple , en la teoría de tipos de Martin-Löf o en el Cálculo de Construcciones .