Here I am, trying a new thing
May 5, 2024Dear Cartwheel,
For a long while now I’ve been working up the courage to writing something approximating a blog. You being a cat and all, I wouldn’t expect you to understand my hesitation, let alone my motivation.
But then I see you staring at the ceiling fan, wondering how it is I manipulate light with the pull of a chain, mystified, learning, and I know there is more to you than I give you credit for.
Pretense is counterproductive to writing. But Cartwheel, I have nothing to prove to you.
Here is what I’ve been thinking about lately.
# The Expression Problem
Okay, Cartwheel, you know Haskell, right?
No?
I recently came across a short
post that helped me understand the raison d’être for
forall
types in Haskell.
Imagine you are developing a library and you model your domain with some abstract data types. Perhaps you define some simple shapes:
data Circle = Circle Float Float Float
deriving (Show, Read, Eq)
data Rectangle = Rectangle Float Float Float Float
deriving (Show, Read, Eq)
You want to give your users something to do with these shapes. All 2-dimensional shapes have an area, so you write a function to produce the area by pattern-matching on the ADTs and–
Circle _ _ r) = pi * r ^ 2
area (Rectangle x y x' y') = (abs $ x - x') * (abs $ y - y')
area (
---- end of file.
---
----- REPL output:
<interactive>:16:7: error:
• Couldn't match expected type ‘Circle’
with actual type ‘Rectangle’
• In the pattern: Rectangle x y x' y'
In an equation for ‘area’:
area (Rectangle x y x' y') = (abs $ x - x') * (abs $ y - y')
Prophet’s post suggested the natural instinct is to define the shapes as components of a sum type, which would make the above code valid at the expense of extensibility. In the interest of allowing us to add more shapes later—or even extend the library in userspace—we should use a typeclass.
This issue of extensibility is part of the so-called “Expression Problem” to which type classes are one solution. I think it is a pretty good solution; writing typeclasses is not too much extra code (it often reduces code!) and they are not too much trouble to understand. They are a nice implementation of a critical idea in programming languages—that data can be associated with behavior in quite complex and overlapping ways.
So you express the idea that all shapes have an area using a typeclass, since this is the idiomatic solution.
class Surface shape where
surfaceArea :: shape -> Float
instance Surface Circle where
Circle _ _ r) = pi * r ^ 2
surfaceArea (
instance Surface Rectangle where
Rectangle x y x' y') = (abs $ x - x') * (abs $ y - y')
surfaceArea (
---
--- Now entering user-land
---
-- We can extend the library with our own shapes, and still use the same old
-- `surfaceArea` function from the `Surface` typeclass!
data Square = Square Float Float Float
deriving (Show, Read, Eq)
instance Surface Square where
Square x y w) = w ^ 2 surfaceArea (
But it is still impossible to perform operations over heterogeneous collections of shapes:
-- This looks like it should work, right?
f :: (Surface s) => [s] -> Float
= sum $ map surfaceArea ss
f ss
--- REPL:
λ> f [Circle 0 0 5, Rectangle 1 1 2 2]
<interactive>:32:18: error:
• Couldn't match expected type ‘Circle’
with actual type ‘Rectangle’
• In the expression: Rectangle 1 1 2 2
In the first argument of ‘f’, namely
‘[Circle 0 0 5, Rectangle 1 1 2 2]’
In the expression: f [Circle 0 0 5, Rectangle 1 1 2 2]
The solution is Existential Types. These types form an opaque, uniform interface to the typeclass methods such that the typechecker is happy with a homogenous collection, but the relevant operations can still be performed.
data WithArea = forall shape. Surface shape => WithArea shape
instance Surface WithArea where
WithArea s) = surfaceArea s
surfaceArea (
--- REPL:
λ> c = Circle 0 0 1
λ> r = Rectangle 0 0 1 1
λ> sum $ map surfaceArea [WithArea c, WithArea r]
79.53982
There is something going on here. Abstract data types, classes, objects, type classes—they all answer the same questions about how to structure our data in modular and extensible ways. Objects are a poor man’s closure, closures are a poor man’s object; and the same holds true for type classes and mixins.
Now I wonder: what programming problem do dependent types solve? And what object-oriented solution was already invented in the 70s that the finest type theorists refuse to acknowledge?
To be honest with you, Cartwheel, I have no quarrel with the type theorists. They are my friends and colleagues, my heroes and mentors. I spend all day writing complex types in Ur/Web. I find the connections between OOP and FP quite fascinating and exciting—beautiful, even.
# Language Feel
I recently wrote a small but complex program in Racket using Geiser in Emacs as my IDE. I usually program in Python or Haskell, but I have a bit of experience in Racket. Cartwheel, these languages feel so different.
Every language has a gimmick or two. Java’s gimmick is garbage-collected objects on a virtual machine. Haskell’s gimmick is laziness and types. Python’s gimmick is dynamism and simplicity. What is Racket’s gimmick? As far as I know, it is macros and languages. Insofar as there is a “right” way to write Racket, the right way is to create small DSLs that help you express solutions to your problem and properly encode the semantics of your domain. I did not do this.
Even with the REPL giving me wonderful affordances, writing Racket felt like floating on air. By contrast, Haskell feels solid, rectilinear, geometric. When I write Haskell, I plan out entire programs by first modeling the types and function signatures and iterating on those before I write a single line of implementation. Haskell makes me feel like an architect, sketching out a blueprint.
Why is this? Working in a richly typed language is like having a conversation with the compiler. The machine assists you, keeps you on track and consistent—but punishes exploration and digression and disorganization. This is a tradeoff I happen to appreciate.
In Racket, I tend to be more hare-brained. I jump around writing little fragments of code, leaving unfinished expressions and throwing out ideas haphazardly. Racket’s homoiconicity and the liveness of the Geiser notebookish interface certainly encouraged this behavior.
Here is another point for the validity of the Sapir-Whorf hypothesis in programming. If we take the phenomenon seriously, can we design languages with intention surrounding the style of programming they encourage?
Programming languages and cognitive science, as fields of study, began at the same time out of the same groups of people thinking about intelligence and human augmentation. Now they feel separated by a wide gap, and we pretend they are not related. I am glad Will Crichton is interested in bringing the insights of cognitive science to programming languages.
Given the stunted state of programming—we appear to be stuck with the assumptions and affordances of the 80s—I fear we are not ready for the revolution in programming heralded by LLMs. I fear the immaturity of our tools for expressing ourselves computationally leaves us unprepared to make full use of the technology of generative AI. This makes it all the more exciting to be working on programming languages right now: the stakes are high for the future of programming.
# Office Spaces
The gruesome banality of suburban office parks holds me with a morbid rapture. Caught in the emptiness between a freakishly large parking lot, a measly green patch with a twiggy tree, and the dull brown brick of a 4-story anonymous office building, I’m searching everywhere for beauty. In its stead, might nostalgia suffice?
In the TV show Adventure Time, villains like Ice King are redeemable, but (spoilers) the final boss is a being of pure chaos. Evil lies on a spectrum with good, implying the ability to become evil from good and good from evil. We all possess some notion of evil. We are capable of understanding evil. Evil is often human. But not chaos. Chaos is unhuman, incomprehensible, the awful marriage of power and ignorance. Evil is drama, but chaos is the tragedy of absurdity. We prefer the wise tyrant to the dangerous fool. For examples of the former acting as defender of the realm against the latter, see Adventure Time’s Ice King, Dark Messiah’s Arantir, Succession’s Logan, and this TV Tropes page.
The modern design trends of offices—the international Airbnb style, the coffee shop consensus, the WeWork—are not evil. They augur nought but chaos, idiocy, dispassion, all that is antithetical to life. Not autocratic narcissistic excess, but a worse fate for society: attrition to the inefficiencies of capitalism without a rational agent which can yoke alien law to human will. A death heralded by the age of average. It is always boring before the end.
How I yearn for the days of olde! When the designers and architects of the mid-century promised technological solutions to social ills. When every office worker was a patient, and Eames and Herman Miller were the doctors dealing in cures.
I’ve been invited to apply to live in MIT’s brand new graduate student dorm, “Graduate Junction” by American Campus Communities. Please, Cartwheel, please tell me who in the world thought I would want to live in a building where the lobby looks like this and this?
Before I go, tell my offices I love them.
# Cozy Sci-Fi
The stark light of a yellow star pierces through the windows of a lonely spaceship, illuminating crumpled bedsheets in the crew quarters, splaying a sunbeam on the pristine cream-colored floor. A bustling market on a remote lunar outpost is host to merchants, criminals, troublemakers and all the rabble dropped there by circumstance and misfortune. Scrappy scavengers laugh over a hearty meal in the mess hall on their old, beaten-up planethopper. Brave explorers on a five-year mission have a moment of respite during shore leave in a Federation solar system. Love blossoms in the vacuum of space. I want to call this cozy sci-fi.
Examples of cozy sci-fi
- On A Sunbeam by Tillie Walden
- The Host by Stephenie Meyer
- Star Trek: The Next Generation by Gene Roddenberry
- Tacoma by Fullbright
- Firefly by Joss Whedon
- Dark Matter by Joseph Mallozzi and Paul Mullie
- Outer Wilds by Mobius Digital (so I’m told; I haven’t played it yet)
Please tell me if you know of others.
The essence of cozy sci-fi
I’m sorry, Cartwheel, but you’re just not the right audience for this. I’d really like to think deeply about what qualities define cozy sci-fi, but that kind of research takes time and effort and I’d prefer to publish something sooner.
I can say one thing right now: it is not a difficult leap between the loneliness of space travel and the warmth humans instinctively create out of circumstances of isolation.
Stay tuned for more?
Gallery
In Tacoma, the para-protagonists live on a company space station under conditions of extreme corporate negligence. But cozy spaces like this one are in no short supply. They indicate the indominable human will to adapt, to find comfort and home no matter the situation. Every personal item conveys quiet rebellion and uncompromising humanism in the face of perilous risk and injustice. Image source: Heterotopias.
In Firefly, the heroes (if you can call them that; they are more like honorable thieves) live on a rusty but reliable spaceship called Serenity. The 14 episodes of the show introduce the audience to many aspects of daily life on the craft, including warmly-lit communal crew dinners in the kitchen. Such moments feature briefly on the show, but they imply that the crew develops strong bonds of intimacy during long, isolating voyages. Furthermore, these human rituals are crucial to the well-being of the protagonists, and they prove that even the more grizzled crew members have deep compassion for their shipmates. When they fall into danger, the audience may recall these moments of familial comfort to understand why the crew of Serenity will do anything to protect one another. Image source: IMDB (Episode 7: “Safe”).
The final episode of Firefly begins with a tour of the crew engaged in quiet moments of leisure during a long and lonely voyage through empty space. Here, Simon and Kaylee flirt in the passenger quarters. Serenity’s pilot and second officer are married and their dedicated companionship features prominently throughout the show. Firefly’s image of sci-fi is full of romance, both in the interpersonal sense and in the contentious romance of remaining outside the law and living on the run. In the former case, Whedon frequently chooses to portray romantic situations as cozy respite from the difficult life of smugglers. Image source: IMDB (Episode 14: “Objects in Space”).
In season 2, episode 9 of Star Trek: The Next Generation, several senior members of the crew play a game of poker together under cozy lighting in their downtime. Similar to Firefly, the protagonists are shown to have bonds of friendship that extend beyond work and circumstance. These bonds are formed in moments of quiet leisure just as much as they are formed in the crucible of challenging situations. TNG takes the time to show us both sides to the life aboard the Enterprise.
The crew quarters in TNG are beautiful imaginings of spaceship interior decor, emblematic of the optimistic futurism that permeates the show. They are luxurious and hospitable, inviting a sense of comfort and personal space uncommon to life as crew on ships in the world today. Windows out to space are the central feature of the captain’s quarters—shown here—which is fitting given Captain Picard’s contemplative demeanor. Image source: IMDB.
Tillie Walden’s On A Sunbeam is the crystallization of cozy sci-fi. The webcomic’s protagonists are not smugglers or explorers, but restorationists. Walden portrays life in space as often quiet, sometimes dangerous, occasionally breathtaking, and always queer. I will let the images speak for themselves. Image sources: On A Sunbeam.
# Further Reading
Cartwheel, I think you should learn to read. You are clearly highly intelligent, and given how you like to attack me when you have the zoomies, you are the apex predator. Why do cats not rule the earth and run society? I suppose they do, in some ways, but let’s be honest: humans did all the work. I wonder if it’s because you cats grow up so quickly. A species with a long time to reach adulthood requires society (or at least a village) to provide supportive structure for both the parents and children to survive. I imagine these phenomena would interact in a positive feedback loop: safety in society permits even longer development, leading to smarter brains and then more society. It seems cats reached a premature local maximum in species evolution.
Well, I have hope for you yet. Here’s some things I’ve been reading so you can learn to be smart like me.
- Cristóbal Scuitto’s Folk (Browser) Interfaces.
- Bret Victor’s A Brief Rant on the Future of Interaction Design.
- Daniel Jackson’s The Essence of Software.
That’s all I have for you.
Good tidings,
Carmel