Functional programming abounds with recursively defined data types.
We often draw these structured values as trees with the root at the top and the leaves at the bottom.
Lazy functional programming allows values (structures) of these types to be “bottomless”, meaning we can descend forever.
There are many examples of how supporting such values gives an enormous boost to modularity.
(See, e.g., John Hughes’s classic paper Why Functional Programming Matters.)
We usually refer to these values as “infinite”, but I’d like to suggest “bottomless” as a more specific alternative, and to point out a limitation that perhaps is not widely noticed.
Although we can descend infinitely in lazy functional programming, we can only ascend finitely.
If I’m traversing a lazy list, there may be infinitely many elements on my right (yet to be visited) but only finitely many on my left (already visited).
While traversing a tree, there may be infinite paths below but only a finite one above (leading to my current position).
In other words, our data is bottomless, but not topless.
What would it be like to go beyond our usual merely uni-infinite data and program with bi-infinite data instead?
With data that is both bottomless and topless?
Continue reading ‘Topless data’ »
The zipper is an efficient and elegant data structure for purely functional editing of tree-like data structures, first published by Gérard Huet.
Zippers maintain a location of focus in a tree and support navigation operations (up, down, left, right) and editing (replace current focus).
The original zipper type and operations are customized for a single type, but it’s not hard to see how to adapt to other tree-like types, and hence to regular data types.
There have been many follow-up papers to The Zipper, including a polytypic version in the paper Type-indexed data types.
All of the zipper adaptations and generalizations I’ve seen so far maintain the original navigation interface.
In this post, I propose an alternative interface that appears to significantly simplify matters.
There are only two navigation functions instead of four, and each of the two is specified and implemented via a fairly simple one-liner.
I haven’t used this new zipper formulation in an application yet, so I do not know whether some usefulness has been lost in simplifying the interface.
The code in this blog post is taken from the Haskell library functor-combo and completes the
Holey type class introduced in Differentiation of higher-order types.
- 2010-07-29: Removed some stray
Just applications in
up definitions. (Thanks, illissius.)
- 2010-07-29: Augmented my complicated definition of
tweak2 with a much simpler version from Sjoerd Visscher.
- 2010-07-29: Replaced
fmap (first (:ds')) with
(fmap.first) (:ds') in
down definitions. (Thanks, Sjoerd.)
Continue reading ‘Another angle on zippers’ »
A “one-hole context” is a data structure with one piece missing.
Conor McBride pointed out that the derivative of a regular type is its type of one-hole contexts.
When a data structure is assembled out of common functor combinators, a corresponding type of one-hole contexts can be derived mechanically by rules that mirror the standard derivative rules learned in beginning differential calculus.
I’ve been playing with functor combinators lately.
I was delighted to find that the data-structure derivatives can be expressed directly using the standard functor combinators and type families.
The code in this blog post is taken from the Haskell library functor-combo.
See also the Haskell Wikibooks page on zippers, especially the section called “Differentiation of data types”.
I mean this post not as new research, but rather as a tidy, concrete presentation of some of Conor’s delightful insight.
Continue reading ‘Differentiation of higher-order types’ »
The post Sequences, streams, and segments offered an answer to the the question of what’s missing in the following box:
I presented a simple type of function segments, whose representation contains a length (duration) and a function.
This type implements most of the usual classes:
Applicative, as well
Comonad, but not
It also implements a new type class,
Segment, which generalizes the list functions
The function type is simple and useful in itself.
I believe it can also serve as a semantic foundation for functional reactive programming (FRP), as I’ll explain in another post.
However, the type has a serious performance problem that makes it impractical for some purposes, including as implementation of FRP.
Fortunately, we can solve the performance problem by adding a simple layer on top of function segments, to get what I’ll call “signals”.
With this new layer, we have an efficient replacement for function segments that implements exactly the same interface with exactly the same semantics.
Pleasantly, the class instances are defined fairly simply in terms of the corresponding instances on function segments.
You can download the code for this post.
dup  =  near the end (was
- 2008-12-09: Fixed
drop default definitions (thanks to sclv) and added point-free variant.
- 2008-12-18: Fixed
appl, thanks to sclv.
- 2011-08-18: Eliminated accidental emoticon in the definition of
dup, thanks to anonymous.
Continue reading ‘Sequences, segments, and signals’ »