Classical (Co)Recursion: Programming

Paul Downen,Zena M. Ariola
DOI: https://doi.org/10.48550/arXiv.2103.06913
2021-03-12
Abstract:Our aim here is to illustrate how the benefits of structural corecursion can be found in a broader swath of the programming landscape than previously thought. Beginning from a tutorial on structural corecursion in the total, pure functional language Agda, we show how these same ideas are mapped to familiar concepts in a variety of different languages. We show how corecursion can be done in strict functional languages like Scheme, and even escapes the functional paradigm entirely, showing up in the natural expression of common object-oriented features found in languages like Python and Java. Opening up structural corecursion to a much wider selection of languages and paradigms -- and therefore, also to a much larger audience of programmers -- lets us also ask how corecursion interacts with computational effects. Of note, we demonstrate that combining structural corecursion with effects can increase its expressive power. We show a classical version of corecursion -- using first-class control made possible by Scheme's classical call/cc -- that enables us to write some new stream-processing algorithms that aren't possible in effect-free languages.
Programming Languages
What problem does this paper attempt to address?
The core problem that this paper attempts to solve is **how to introduce and apply structural corecursion in a wider range of programming languages and paradigms**. Specifically, the author hopes to show that structural corecursion is not limited to lazy pure - functional languages (such as Haskell), but can be implemented in a variety of programming languages, including strict - functional languages (such as Scheme), dynamically - typed languages (such as Python), and object - oriented languages (such as Java). In addition, the author also explores how to combine computational effects to enhance the expressive power of corecursion. ### Main Objectives 1. **Introduce the Basic Principles**: Introduce the basic principles of original structural corecursion in different practical programming languages. 2. **Demonstrate the Expressive Power**: Point out the expressive power of different forms of structural corecursion and illustrate these powers through a series of examples. ### Specific Contents - **Comparison between Recursion and Corecursion**: - Recursion is usually used to handle finite data structures, ensuring that a definite result can be finally obtained. - Corecursion is used to generate infinite or large - scale data sets, allowing data to be generated and consumed step by step. - **Applications of Corecursion**: - The author starts from corecursion in the Agda language and shows how to use copattern matching to generate infinite streams. - Then, the author shows how to implement corecursion in Scheme, using the `call/cc` control operator to capture the classic corecursion concept, so as to be able to write some new stream - processing algorithms. - Next, the author explores how to express corecursion in Python and Java, especially how to use object - oriented features to implement corecursion. - **Combining Computational Effects**: - The author discusses how to combine corecursion with computational effects (such as exception handling) to enhance its expressive power. For example, in Python, exceptions can be used to terminate the generation of streams in advance or skip intermediate elements. ### Examples - **Corecursion in Agda**: - Use copattern matching to define infinite streams, such as the `Stream` type. - Generate complex infinite streams through higher - order functions such as `coiter` and `corec`. - **Corecursion in Scheme**: - Use `call/cc` to achieve resumable corecursion control and show some stream algorithms that cannot be expressed with pure corecursion combinators (such as anamorphisms and apomorphisms). - **Corecursion in Python**: - Use persistent objects to implement corecursion, avoiding that each method call affects the future state. - Use exception handling to simulate different forms of streams and add new functions such as early termination or skipping intermediate elements. - **Corecursion in Java**: - Discuss how static types interact with corecursion and its combinators, especially formalize the feature - based stream type hierarchy through subtype relationships. - Distinguish between safe operations (which can always produce results within a finite time) and unsafe operations (which may cause the program to hang). ### Conclusion Through these examples, the author hopes to show that the corecursion design pattern is not only suitable for generating infinite data, but can also be applied to different programming paradigms. This helps to promote the concept of corecursion to a wider programming environment and make it a generally applicable programming technique.