Information Economics

Some say the information revolution happened in the 1970s upon the advent of the personal computer, some say it happened in the 90s when the internet reached critical mass. These were incredibly important events in the history of humanity, but I claim the information revolution has seen only its beginnings.

Consider the case of the automobile. The transportation revolution did not happen overnight in 1897 when Rudolf Diesel built the first combustion engine. Instead, it happened gradually as the world was changed around the people as a result of this new technology. Oldsmobile and Ford refined the process of creating cars, and with that transformation came a new kind of economics based on the assembly line. The transportation revolution came to its apex upon the construction of the interstate highway system, upon which the choice of where a person lived and where he worked became decoupled.

We have seen the analog of the advent of the combustion engine and the beginning of Ford’s innovations. “The Information Superhighway” is superficially related to the creation of the highway system, but I think of that as an echo of the revolution of the highway system, not the revolution of the information age. We are at the creation of the assembly line, before it gained wide adoption. Google is Ford.

The reason is that the information age is about information, which is a totally different kind of beast than traditional commodities, around which our economy is based. As few as five years ago, businessmen tried to charge $50 for ready-made software sitting on a shelf as if it were a television or a bag of rice. But that is an ancient conception that completely fails to reflect the economics of what a software package is.

To see this issue clearly, we have to step back from our personal conceptions of money as a thing which allows us to live and operate in society, and think about it in terms of what it was when it was created: an abstraction for trade, which served to make society as a whole more efficient. Money is about allocating scarce resources to where they will most benefit society. It isn’t perfect at doing that job, but it is pretty damn good all things considered. It works way better than communism, which puts that allocation in the government’s hands.

Back to the television and the software package. A single television requires resources to produce. When you buy a television from the shelf, you are communicating “a television has value to me, please continue to allocate resources to produce televisions”. As society moves beyond the need for new televisions, people stop buying them, money (an abstraction for resources) stops flowing to the manufacturer of the televisions, and the company shrinks or dissolves so that those resources can be allocated somewhere where they can more benefit society.

Try to apply this story to software. Software costs resources to produce initially, but after it is on the shelf, all the resources it will ever consume have already been spent during its development, modulo its useless and wasteful packaging. Now there is a component of continuing to improve the software, but the cost of improving the software is not proportional to the number of users the way the cost of producing televisions is proportional to the number of people that want televisions. While treating software as a commodity does serve to compensate the creator for producing the software, when seen from the perspective of the economy as a whole rather than a single business, it makes no sense. The idea of commodity software is a misallocation resources.

Fortunately, the idea of commodity software is gradually fading away. We have mostly done away with the wasteful practice of putting software — essentially free to reproduce — into boxes, which have a cost to reproduce and are only advertisements until they are thrown away by the purchaser. But the model persists in the App Store, among other places. But note how the great Giants of the age are no longer using this model. Apple is profiting off of others using this model, but they are not using it directly. Google and Facebook will have nothing to do with it. Microsoft is dying a slow, painful death.

While there is a social realization that the old commodity model isn’t working anymore, it is not clear to me that anyone sees where it is headed. Google has hit a sweet spot where they can provide value to everyone without charging consumers any money — by collecting data about people, they make it easier for producers and consumers to connect when they stand to benefit from each other, and they found a nice place to skim compensation off of that arrangement. Google essentially has one very valuable product. Apple’s business model is basically that of a hardware company. But how does a typical software company work in the new age of information?

To explore this idea, I will take the vantage point of looking at society as a whole and follow the scent of efficient resource allocation. Resources are required to produce software in the first place: we need ideas, programmers, testers, and marketers. After the software has been conceived of, written, and tested — that is, at the point when the consumer uses the software — all the resources required for producing the software have already been expended. It is nonsense to charge people at this point; society would benefit more if you simply gave your software away, because the cost of doing so is (almost) zero. We need a way to pay for ideas, programmers, testers, and marketers. The resources required for providing a product are proportional to the difficulty of its creation, not the scale of its distribution.

I picture a combination of Kickstarter and an economic extension of UserVoice due to John De Goes. Allow people to pledge money for the improvement (or creation) of a product or feature, to be paid when that feature is usable. The features that are most valuable to people will have the most money pledged to them, providing incentive for the company to develop those features. We are now allocating resources where they need to be: in improving the product, rather than paying for the vacation of somebody who created valuable software in the past, somebody whose mind and expertise would be more beneficial to society developing or improving their product. This is just one idea, I’m certain there are other models that will accurately reflect information economics as well. In particular, this model compensates those who implement an idea, but not those who came up with the idea in the first place, which is a place for improvement.

Observe how this new type of model has shifted the economic emphasis to one derivative higher. People are compensated for continuously improving their product and creating new products, rather than having one great idea and banking on it. This may frighten innovators: their great innovations now stand to make them less money; we now need to constantly work to create value instead of sitting atop a great idea allocating resources. But look at it from society’s perspective: we are coming up on an age of immense growth, in which every worker in the economy is seeking not just to continue the status quo, but to improve it! Everyone is an innovator or an enabler of an innovator. And this all comes from software being free to copy. When something is free to copy, everyone should have equal access to it. Any other way is short-changing society.

It’s time to stop clinging to software as if it is consumed when it is used. There is an economic boom waiting to happen, if we just let information resources flow the way they want to.

Another way to support the new economy is to Flattr this. ;-)

Announcing CodeCatalog

I’d like to share what I’ve been working on instead of homework for the past month: codecatalog.net. From the FAQ:

CodeCatalog is a lot like a wiki for source code. We aim to socially build a database of high-quality, well-documented, instantly-usable code in a variety of languages.

It is the fruit of my thoughts’ recent focus on reusability. I noticed that because of purity, Haskell was very close to being able to have a “database of all reusable code ever”, and I kept focusing on what language features were missing from languages that prevented that. After sharing the idea with Max (cofounder of Hubris Arts), we determined that the main missing feature was, er, a database of all reusable code ever. CodeCatalog is the first buddings of an attempt to create one.

Check out the FAQ for a glimpse of our philosophy. Haskell sophisticates might be able to see beyond my simple wording into the underlying vision — that was my intent at least. I’ll write a post soon describing our deeper plans in more detail. We’ll be working on this all summer, and if we meet our goals, by the end of the summer it should be pretty freaking cool. :-)

Oh, the code that we have on the site so far is mostly Python and Javascript, mostly because that’s what we wrote the site in and we were eating our own dogfood while developing it. But Haskell is also supported.

Anyway, fellow Haskell community, I encourage you to check out the site. We would appreciate any feedback you have about it. There’s a UserVoice tab on the right if you’re into that kind of thing. Thanks. :-)

And if you would like to support us financially, you can always Flattr this.

The essence of metastrategy

A recent post on Less Wrong, Levels of Action, reminded me of a game I created whose dynamics I wanted to explore. I still have not explored the dynamics to a great level of depth, but I thought it would be interesting to the nerdy community that reads my blog.

The idea came after playing Castle Wars 2. In that game you try to build your castle as tall as possible while keeping your opponents castle as short as possible. The basic game dynamic is an action/meta-action trade off: (oversimplifying) you can play a card to gain 10 bricks, or you can play a card to gain one brick per turn for the rest of the game. I was surprised by the amount of subtlety derived from such a simple dynamic, and I recommend the game to anyone wanting to kill an hour. It’s not the best game ever, but it’s not as trivial as it at first seems.

I wondered what would happen if I removed the cards, the weapons, the defense from that game and replaced them with more levels of this same dynamic. Here’s what I came up with.

You can play it with a chessboard and poker chips (my old game design standby). You don’t need 6 of the rows of the board. Each player plays on a side of the board, and has eight squares which we will label, from left to right, 1 to 8. Each square can have up to eight chips in it. The goal of the game is to get eight chips in the eighth square. Here is how play proceeds:

On your turn, place a single chip in any of your squares. Your opponent does the same. Before each turn, “cancel out” any chips that both players have on corresponding squares. That is, if you have 4 chips on the 5th square, and your opponent has 5 chips on the 5th square, remove 4 chips from both, so that you have none and your opponent has one. Then (still before your turn) duplicate each square to the next higher position and truncate down to 8. So before this action if your eight squares had these values:

0 0 1 4 5 2 0 3

Then after this action, the state of your board will be:

0 0 1 5 8 7 2 3

Another way to think about it is that you slide a copy of your board one position to the right and add (then truncate).

Then place your new chip, and your opponent takes his turn. That’s it. The first player to eight in the eighth square wins.

Despite this game’s simplicity, I have been unable to devise a good strategy for it. The strategy for the game seems to revolve around estimating the length of the game. If you know how many turns the game will last, it is fairly easy to determine how to play optimally. But knowing how long the game will last is not so easy to determine.

Try it out, think about it. Let me know if you discover anything.

Like this post?
Flattr this

Change a-stirring

As is the nature of college life, my consciousness is filled with lots of lost ideas, floating around like strands of RNA trying to construct their counterparts. This post is an attempt to write some of them down, just to bring my awareness to them and perhaps to crossbreed with others’ random ideas. No, I’m not in a biology class, though you wouldn’t know it from this paragraph.

I feel like I am in the midst of a spiritual awakening. I am certainly epiphanizing a lot. Knowing my history, I am probably just in an epiphanizing mood, and the true learning I am acquiring from this time in my life will become clear to me in about half a year. I feel an increased devotion to integrity and “right action” (perhaps dharma is an appropriate word). I am developing my ability to approach all situations from a place of love and compassion toward myself and others. This involves taking opportunities to stretch when I realize I am avoiding something from a place of fear or discomfort, taking time to mini-meditate and focus, and creating external reinforcement for my internal goals (this was a huge realization for me).

Last night I had an epiphany about mortality. It was the most potent realization I have had that my consciousness ends. That whatever I do in my life, at some point I will no longer be able to observe the consequences, that the world will continue without me. So even if I do help to change the world for the better (as we all wish to), at some point I will have to trust it to continue for itself. It makes me want to make my impact now, because every day that passes is a missed opportunity to do something meaningful. Anyway, this sentiment is tired, I have read it many times before, and I have to arrive at it myself for it to mean something. Without loss of generality I assume that I am similarly failing to communicate it to my readers.

This state of mind has stirred up an internal conflict. I went back to school to finish the degree I started, and now I feel like I have something to say and am too busy with school to devote energy into saying it. Do I wait until I finish school? I am just now breaking a detrimental pattern in my life: that of waiting for some other event to happen before I do the right thing. It’s a form of procrastination. I see it coming out through my school dilemma: I really want to work on this economic responsibility project, but not until I finish school. Eighteen months from now who knows whether my passion for this project will persist.

I am holding to my commitment. I am certain that school seeded the ideas that pushed me in this direction. Perhaps I can trust that continuing school will help me continue to refine the idea, so that when I finally finish my picture will be so clear there will be no stopping me. Indeed, one quality of my current idea is that I don’t really know how to execute it — I have some ideas, but none that is obviously the right way to go.

My recent thoughts about social issues share a common thread: the stable equilibrium. The areas in society where we have the most trouble (from my present, incredibly biased perspective) are those areas that resist gradual change. For example, relating to the theme of my my last post, Americans are spending their money irresponsibly because there is not a good source of information about what constitutes responsible spending according to each person’s values. Many people know what kinds of companies they would like to support and which they wouldn’t, but the information to take that goal and derive which products to support is not available. The reason this is a stable equilibrium is that companies must choose to reveal this information, and in the current climate, any company that chooses to reveal this information puts itself at a disadvantage with respect to the ones that do not. If the culture shifts such that most companies reveal this information, then it looks suspicious not to reveal yourself and you put yourself at an advantage by revealing your details. But there is no mechanism to get from the former to the latter — the former reinforces itself. Indeed there are many powerful people with a vested interest in maintaining the status quo.

A similar pattern arises in the state of public education. Schools are judged and funded by standardized tests. It is the opinion of many progressive educators that the nature of the tests is too broad and shallow, and reinforces a superficial, fact-memorization-based education, the kind that doesn’t really produce competent students. But any school that experiments with its methods will deviate from these tests before it has a chance to show long-term achievement, and thus get its funding cut (or if it is a single teacher, the teacher will get fired by No Child Left Behind). The system discourages variation and reinforces its own status quo, so its problems cannot be evolved out by the natural forces of gradual variation and competition.

Examples of such equilibria abound. Reforms must be taken to the top, which is a dangerous place to reform because the effects are so sweeping. Reforms that should be taken to the top are those that enable competition and variation, so that gradual improvement is allowed to happen. Unfortunately, for the above two examples, I cannot think of what such a policy would be. (The latter could theoretically be addressed by privatizing education — indeed many private schools have very effective new methods — but there is a cacophony of social issues that comes with that, which includes, among other things, further widening the class gap).

In order to focus discussion, I will save my (relatively few) technical ideas for another post.


Flattr this

The Almighty Dollar

@luqui – Buy the change you wish to see in the world.

This Gandhi rip-off tweet is a summary of an idea that I would like to share in more detail. Last week I got sniped and swindled by a street peddler of Children International, a charity organization, largely due to a weakness of boundaries I had at the time. I wasn’t really feeling charitable, and I just wanted him to stop talking at me without being rude. The most immediate way out to my uncreative brain was to sign up and cancel later. I may have felt more charitable if it wasn’t so much money — $30 per month — but I was sure that I was going to cancel, and put it on my immediate to do list.

When I had a moment to clear off some items on the list, as I was looking up the number to call, I pictured the phone call. Having already done research and found that the organization was legitimate and even efficient, there was no excuse there. Then I was going to say “I just can’t afford it right now”… which would be a lie. I am a poor college student, but I am still privileged by college, and I spend about $300 per month on food. Saying I couldn’t afford $30 per month is just outright wrong. Lying to a charitable organization is beyond my (comparatively flexible) morals.

I couldn’t find a way out that was consistent with my self-image. Thus, I haven’t canceled, and I don’t think I’m going to. Faced with the inability to prove that I shouldn’t spend this money, I began to search for reasons why I should. And the above twitter quote is the one I found, in a nutshell.

America is a severely capitalist nation. It has a fair amount of socialism mixed in, but it is still one of the most money-driven countries on this planet. We criticize big corporations in general for being immoral, corrupt, greedy entities that are ruining the world. They have great power, and they wield it in offensive ways. Damn them! Clearly pure capitalism can’t support a humanitarian world.

I used to believe this. But let’s think about it: from where is their power derived? From the economy of their country, of the world. They have tons of money and power because we give it to them. They provide us with valuable services, and we in turn compensate them with money, which is essentially equal to power in a capitalist society. And then we complain when they use that power in a way that offends us. So we are not really unconditionally giving them power: we wish to say “you can have the power to do things we agree with”. Not really power at all. We want to use their services without compensating them.

A dollar is a vote! It is a unit not only of trade, but of trust. But we routinely buy products from companies we do not trust. And no wonder they do evil things… we gave them a symbol of our trust without actually trusting them. We “the proletariat” are the ones who are ultimately producing the value in this nation, and we are collectively being compensated for it. Taken as a whole, we have enough power to match or exceed any corporation (I haven’t done the research, but I think the principle is pretty easy to agree with). We are being very irresponsible with our money — our tokens of trust — giving it to people who we know are evil. We are creating the evil in the world, simply by being fast and loose with our money.

It is widespread knowledge at this point that Monsanto is a profoundly evil corporation. They produce genetically modified plants, and then claim ownership of any plant that crossbreeds with it (using their money to out-lawyer any farmer who disagrees). With the chaotic nature of seeds in the wind, left unchecked they could eventually claim ownership of every plant in the world by seeding a single field on every continent. They buy out politicians to allow them to pollute acres and acres of United States land. The world would be a better place without them — their technology is great, but their behavior as an entity is abhorrent.

A conversation comes up in a grocery store about the evil of Monsanto, and while complaining and loathing the evil in the world, they pick up the cheapest loaf of bread and put it in their basket, thereby handing the evil in the world another token of their trust. If the world refused to buy any Monsanto-derived food, Monsanto would die. Poof, evil extinguished! The choice in what food you buy is asking you a question — do you prefer cheap food, or a moral world? If you buy Monsanto-derived food, you are saying you prefer cheap food. And the world really does listen.

I want to live in a world in which every person has an equal shot at equal lives (if you want more, you get less of a shot). But that hardly describes the Earth. Is my desire for this ideal Earth greater than my desire for three SubWay sandwiches per month? Could I put up with putting in a little more effort to make my food in exchange for helping the world to achieve this goal? Would it be worth it to you? If you say yes but don’t pay for it, you are lying. This isn’t hyperbole. I consider failing to “put your money where your mouth is” an outright lie.

How many proud Americans lie every day? Are you one of them? I still am. I am working to change that in myself.

Do your research! Pay for things made by companies whose behavior is agreeable to you. Don’t just look at the price. Tell the truth about your vision for the rest of the world, the future, even just a little bit. We, the hard-working, moral people of this planet wield most of the power. Let’s use it responsibly.

Buy the change you wish to see in the world.

(Do you value posts like this one? Well… Flattr this :-)

Connectedness

I’m a student of the University of Colorado again. I’ve gone back to finish my bachelor’s in mathematics, which essentially involves fulfilling a bunch of core requirements. I’m going to start the discussion by mixing my experience of one class (religions of south Asia) with a concept from another class (connectedness from topology).

Last spring I took my (now ex-)’:girlfriend on a trip to Hawaii. While we were there, we attended a weekend immersive class on Sanskrit. The class was very “new-agey” — we chanted, meditated, in addition to learning Devanagari (the Sanskrit/Hindi alphabet) and something about Indian religion. The ideas combined with the approach fascinated and inspired me. I have never been much of a religious person; the religious ideas I had heard of always sounded a bit naive and silly. But this new approach gave me a glimpse of another way of looking at the world: the words of the Bhagavad Gita played with the gods, using them half as entities, half as concepts. The philosophical ideas, language, and religion we studied were clearly inseparable, all connected and synthesized into a single world view. Further, this world view seemed to incorporate my objections to the naivety of western world views — emphasizing the duality in all things, focusing not so much on right and wrong but on purpose and spirit, using the malleability and metaphor of truth.

My curiosity whetted, I enrolled in a class about Hinduism at the university. So far it has been a disappointment. What drew me to these ideas in the first place was the connectedness and duality — the yin and yang, so to speak — I perceived in the world view. And we have started by drawing thick lines categorizing the different approaches to divinity. An especially potent event in bringing to my attention my disappointment with the class occurred during our discussion of Bhakti. The professor began to describe the philosophy of Bhakti: that connecting with the divine is about love and devotion, that the details of ritual are not as important as a true spiritual devotion to god. Immediately after this description, the professor wrote on the board BHAKTI RITUALS. Um, teacher, did you not feel that just now? How did you build your immunity to cognitive dissonance?

We have been categorizing, deconstructing, analyzing this beautiful philosophy as if engineers. After the class I suspect I will know many facts, but have no understanding. If I were to talk to a yogi, he will consider me no closer to understanding his spirituality than any other American out of the hat. This is disappointing, since I don’t consider myself to have learned something until I understand it. We have a Hindu temple here in Boulder; I hope to find a way to study there and use the class as a supplement.

But why I am really writing this post is to help me to grip a vague sense I felt as I was processing after the BHAKTI RITUALS class. I am in a topology class this semester, and we are learning set-theoretic point-set topology. The constructivist in me winces every few minutes, lamenting the non-computability of everything we are discussing. I think the same cognitive orientation is fueling my dissatisfaction with the Indian religions class and my taste for constructivism. Classical mathematics seeks to separate the world into true and false, existence and nonexistence, equal and inequal. The inclusion of the law of excluded middle as obvious is evidence of this, as is the surprise felt by the mathematical world over Gödel’s incompleteness theorem. “What? We can’t eventually separate everything into two categories?!”

If you ask a set theorist whether ℕ = ℚ, they will probably say they are not equal (although have equal cardinalities). If you ask a type theorist whether ℕ = ℚ they will say “huh?”. The question cannot be answered, for we must consider what it means to treat 1 : ℕ as a ℚ, and we don’t know how to do that — not without a function that shows how. Indeed, in constructivism we have to be careful when talking about real numbers, since the set of observations matters, i.e. it matters how we look at them. And for any reasonable construction of the reals, their connectedness falls out of the constructivism of the theory: we cannot separate them into two categories in any way. A set theorist can, and has to define himself into a more realistic world where he can’t using the mechanism of topology.

Mathematicians are probably getting upset at me or thinking I’m an idiot. This isn’t a mathematical post, it’s philosophical, thus my fuzzy intuitive discussions. If you have the desire to leave an emphatic corrective comment at this point, maybe take a step back and try to make out the landscape with me. I don’t consider any of this true, I’m just trying to get a feel for the philosophically general idea of connectedness, outside of a particular formal system. I have the impression that we can think of the world — the real one or the mathematical one — this way and it might lead to a more accurate, if less “clear-cut”, way of thinking.

The pure untyped lambda calculus is connected in the Scott topology. This fact has fascinated me since I heard of it, trivial though it might be. We are used to adding traditional totally disconnected types to the lambda calculus and pretending bottoms don’t exist. I have been curious about what it would look like if we embraced this connectedness and extended lambda calculus with connected concepts. They may play more nicely in a connected system. I still have not made any concrete progress on this idea, but it appeals to me as potentially beautiful and powerful. Maybe we are computing in an awkward way without realizing it.

Did you like this post? Accelerate the flow of Karma :-) Flattr this

Designing with Interfaces

In this post I will share a personal discovery about object-oriented design. It is so simple and obvious that it may not be news to experienced OO programmers. However, it should be noted that before I became a Haskell nut, I was a dedicated OO programmer for 7 years. I occasionally empolyed the pattern in my designs without realizing its full generality. So it may yet be news to you vets.

I came across it when exploring the consequences of my recent post, Encapsulation Considered Harmful. I was trying to design a concept language around the idea, and realized that the language design I kept coming back to could be mostly encoded in existing languages.

Here’s the rule: never reference a class directly — always go through an interface. This includes creating new objects — go through a factory interface or take it as a parameter instead.

Obviously this rule cannot be followed 100% because you’ve got to give a concrete instantiation at some point. But push that as far “up” in your program as possible. Also, doing this 100% in contemporary languages would probably involve too much boilerplate. That’s okay, it can be done piecewise, and many of its advantages can still be reaped if it is done partially.

We have recently done this refactor on our game, and I have to say, it is gorgeous! I really like the clean, uniform way it separates concerns. More importantly, it is an abstraction instead of an encapsulation mechanism. That means that when code doesn’t depend on a particular detail, you can always substitute something else for that detail. Keep that property in mind, it will guide you in applying this pattern correctly.

Here is a simplified example from our game. We used to have a class FileSystem to access the filesystem. ProgressResult<T> was a class that monitored the progress of loading a file from disk and yielded a T when it was finished. Unit is the trivial type: struct Unit {}.

class FileSystem
{
    ProgressResult<List<string>> List();
    ProgressResult<byte[]> Load(string filename);
    ProgressResult<Unit> Save(string filename, byte[] bytes);
}

And in our World class, a class for the main game interface, we used it like so:

class World
{
    FileSystem filesystem;
    public World(...) {
        filesystem = new FileSystem();
        ...
    }
    // using methods on filesystem here
}

After applying this pattern, it becomes:

interface IProgressResult<T>
{
    ...
}

interface IFileSystem
{
    IProgressResult<List<string>> List();
    IProgressResult<byte[]> Load(string filename);
    IProgressResult<Unit> Save(string filename);
}

class FileSystem : IFileSystem { /* as before */ }

class World
{
    IFileSystem filesystem;
    public World(IFileSystem filesystem) {
        this.filesystem = filesystem;
    }
}

See how we avoided creating a filesystem in World, and instead took it as a parameter? World is now more flexible than it used to be: we can (and did!) instantiate it with a disk filesystem and an Amazon S3 filesystem. They have different sorts of ProgressResults too, thus that is also an interface.

Now, if you go to apply this pattern in your project, you might find that it breaks down for more complex designs. It’ll do that if you aren’t precise about your phrasing. For example, in another part of our project we had the following combinator library for our UI:

class UI 
{
    public static UI Over(UI over, UI under) { ... }
    public static UI VerticalGroup(params UI[] uis) { ... }
    public static UI Window(string title, UI contents) { ... }
    public static UI Button(string text, Action onClick) { ... }
    // some non-static members for inspection
}

To abstract over these implementations, we need to promote these static functions into methods on a factory-like interface. It may seem that this is the way forward:

interface IUI { /* the non-static members */ }
interface IUIModule 
{
    IUI Over(IUI over, IUI under);
    IUI VerticalGroup(params IUI[] uis);
    IUI Window(string title, IUI contents);
    IUI Button(string text, Action onClick);
}

But this is not the way. Imagine if you were to construct some IUIs with a SilverlightUIModule and then try to combine them (with, say, VerticalGroup) with a UnityUIModule. What is the unity module supposed to do with silverlight UIs? This design flaw will show its head much earlier than this predicament, however: you will find in UnityUIModule that you need to downcast the IUIs you get into a specific type. Downcasting is an indication that you are doing it wrong. The correct way is to make IUIModule parametric in the UI type:

interface IUI { /* the non-static members */ }
interface IUIModule<TUI> where TUI : IUI 
{
    TUI Over(TUI over, TUI under);
    TUI VerticalGroup(params TUI[] uis);
    TUI Window(string title, TUI contents);
    TUI Button(string text, Action onClick);
}

Now UnityUIModule implements IUIModule<UnityUI> and SilverlightUIModule implements IUIModule<SilverlightUI>, so it is a compile-time type error to pass a silverlight UI to a unity combinator. In addition, you do not need to downcast: the UnityUIModule now knows statically that it will only be passed SilverlightUIs.

One thing remains… how are you supposed to use that damn module? Surely you don’t make every class that uses a IUIModule parametric in the TUI parameter like this:

class World<TUI> where TUI : IUI
{
    IUIModule<TUI> uiModule;
    public World(IUIModule<TUI> uiModule) {...}
}

Type parameters would accumulate in classes, and every time you used that class you would have to write all those fucking type parameters. That can’t be the way to go!

Well… actually… remember the rule? You never reference a class concretely, you only go through interfaces. And the interfaces don’t accumulate type parameters from usages in the implementation like classes do, they only accumulate type parameters from the cleaner and scarcer usage in interfaces. So the worry of unsightly verbose code is unfounded. It’s fine, let the type parameters accumulate, they are a way of stating your assumptions. They tell you exactly how a class may be reused. So to defeat this notational burden in this example, we must continue the pattern: create an IWorld!

As you do this, all your assumptions will bubble up to the top of your program. Each more complex thing is parametric in all the simpler things it is made of. When you go to write code that can actually be executed, you will find an ocean of flexibility: you basically have created a rich combinator library for your domain, allowing it to target multiple underlying frameworks easily, getting multiple different (reasonable, even desirable!) behaviors just by passing a different parameter to some object you are building at the top level. Mmmm, parametricity.

(For dynamically typed languages, duck typing will mostly take care of this pattern for you. But the design motivation remains, make your code parameteric: take parameters saying where it should get the objects it is creating and the functions it is calling rather than referencing them directly!)

Did you enjoy this article? Let me know and Flattr this. I appreciate it.

Return of the Daily Improvisation

For a year starting in 2006, I recorded an improvisation every day and posted it on this blog. But I since moved from my own server to WordPress.com, and had nowhere to put my recordings, and I stopped.

I remember how much I enjoyed that and how much it helped to improve my improvisational skills, since it was more than sitting down and letting my fingers move. It encouraged me to develop a theme, and to give a song a beginning, middle, and end. So I have decided to start them up again, posting on YouTube where they will hopefully have more permanence. People who are interested can subscribe to my YouTube channel, and the Planet Haskell RSS feed can remain lean and on-topic.

I really enjoy playing these. I hope you enjoy listening to them.

My Daily Improvisation YouTube Channel

Encapsulation Considered Harmful

You heard me. Encapsulation is an obstacle to the reuse of code.

When I say encapsulation, I mean having a region of your program that knows or has access to some information about the implementation of something, and hiding that information from the rest of the program. If you have another definition of encapsulation, I’m not arguing against that.

Why do software engineers encapsulate? I claim it is for two major reasons: (1) to reserve the right to change the encapsulated code later without breaking anything, and (2) to minimize the propagation of assumptions through the program. To illustrate this, consider the following C code which uses a (supposedly) abstract List type:

int sum(List* list) {
    int i;
    int accum = 0;
    int length = List_length(list);
    for (i = 0; i < length; ++i) {
        accum += ((int*)list)[i];
    }
    return accum;
}

This code breaks encapsulation. It assumes that List is represented as an array. So if we wanted to go back and change List to a linked list because it is more efficient in the majority of cases for which we are using it, sum would break. (In this example, it would break very badly — i.e. it might not even segfault but instead return some nonsense number)

Here is an example of code that correctly respects encapsulation.

int sum(List* list) {
    int i;
    int accum = 0;
    int length = List_length(list);
    for (i = 0; i < length; ++i) {
        accum += List_get_elem(list, i);
    }
    return accum;
}

If you’re about to object that we should have exposed an iterator interface instead of a indexed get interface because we knew we wanted to change it to a linked list, I preemptively respond that we didn’t know that at the time — as in most code, when you are encapsulating, you don’t usually know what you’re going to come back to change — if you did, why didn’t you just write it like that in the first place?

The two reasons above are noble. They promote flexibility and simplicity, so that the minor decisions we make do not ripple their way through our architecture, making it impossible to change or understand. It takes the pressure off.

Although I agree with the goals, I believe this is the wrong solution. I think we should turn the barriers inside-out, and use only encapsulation’s dual: abstraction. When I say abstraction, I mean code that is defined polymorphically with respect to its assumptions. The above C code is abstract with respect to the list argument, since we can pass it any list we like. It is not, however, abstract with respect to the the List type and its operations — it fixes a single choice.

Encapsulation and abstraction are duals in the following sense: let’s say your program is defined in two parts A and B. A knows some information C, and B does not. There are two ways to look at this. A encapsulates C, or B is abstract with respect to C. That is, if you change C, you have only affected the specification of A, and B reacts polymorphically. So just divide your program at an information boundary — one side is encapsulating, the other side is abstracting.

While mathematically they are two sides of the same coin, there is a very real software engineering difference between them. Let’s say you are have three functions which use your abstract interface: sort, reverse, and frobnicate (some complicated business logic that can’t be written in 5 lines). With encapsulation, you might have this sort of usage graph:

And then, in one fell swoop, you can change it to:

That’s power, that’s flexibility. But… it’s lacking something. Now we have another part of our program which uses arrays, and I sure wish we could use that sort code we’ve already written. But we need that sort code for lists. Hmm, well we could copy and paste. But that sucks, maybe we could go back and make sort polymorphic in the list type. Yeah, that’s the right way to do it.

But, then why didn’t we just do that in the first place? Look what happens when we do:

Look at all those combinations. Those are the possibilities for code reuse without changing anything. Imagine if every encapsulation you made was an abstraction instead. Your usage graph would be basically black with arrows. But these aren’t bad dependency arrows, these are good reuse arrows. These are your possibilities for correctly using code that has already been written.

So I suggest: instead of advertising your guarantees and hiding details, advertise your assumptions and abstract over details. This has a pretty profound effect on the way your code is structured — like I said before, it turns all the encapsulation barriers inside-out.

My inspiration for this idea came from studying the form of mathematical theorems. They advertise their assumptions prolifically: “given a ring R with (+) and (*) as operations, …”, as opposed to “a real number has (+) and (*) and some implementation details”. This allows theorems to be maximally reusable, since although the mathematician was thinking about real numbers when he proved the theorem, he realized the same logic could work on any ring — including the integers, modular integers, matrices, and new things that were discovered later.

Object oriented programming seems to get close. One can consider a class (or an interface) as the specification of an assumption, and an instance the implementation of an assumption. Then you just take parameters that correspond to your assumptions, which are nicely bundled into classes so you don’t have to say “I use (+) and (*) and (-) and absolute value and …”. But this essential idea is muddied up by all sorts of crap, both in the language design and in popular usage.

I started to list the features we need to add/remove from OO languages to make them support this style, but it just got long and nitpicky. So I’ll just say this: I think we should be using objects differently. Objects as implementations of assumptions, not as “agents”. A natural number is not an object, The Natural Numbers is an object. As generics gurus are noticing, this:

interface Number {
    Number operator + (Number y);
}

has got to go. The assumptions are not specified properly — you are requiring that + take any kind of number whatsoever, when we probably mean the same kind of number as on the left side. What does it mean to add 2 (mod 4) to 7 (mod 13)? Instead we are learning to write:

interface Numeric<N> {
    N operator + (N x, N y);
}

That’s the right way. Notice that, although it is specified with different notation, N is just another abstract member of Numeric. We specify the set and its operations together, but the set is distinct from the interface. The interface is the name for the assumption of such a set. In some cases the interface and the set can be bundled into one, and it is these cases that provide most of the study material for OO design. But inside the soul of pop OO lies a form of modeling that is so much more powerful.

To reiterate, this is not breaking the guarantees of encapsulation — anybody who uses Numeric gets encapsulation for free. They are not allowed to see the details of N, just as if you had encapsulated it. It’s just that now you can swap out different N’s in the same code, where you couldn’t before.

I am pleased to see software engineering practice slowly converging on this already. I just thought I would point out the uniform rule behind it. Next time you write an encapsulation, ask yourself, what would it look like to make the users of this code abstract instead? Is it a small enough notational burden to do it that way? If not, what kind of language would allow it to be?

Did that give you something to ponder about? Flattr this

Searchable Data Types

A few years ago, Martín Escardó wrote an article about a seemingly-impossible program that can exhaustively search the uncountably infinite "Cantor space" (infinite streams of bits). He then showed that spaces that can be thus searched form a monad (which I threw onto hackage), and wrote a paper about the mathematical foundations which is seemingly impossible to understand.

Anyway, I thought I would give a different perspective on what is going on here. This is a more operational account, however some of the underlying topology might peek out for a few seconds. I’m no topologist, so it will be brief and possibly incorrect.

Let’s start with a simpler infinite space to search. The lazy naturals, or the one-point compactification of the naturals:

data Nat = Zero | Succ Nat
    deriving (Eq,Ord,Show)
infinity = Succ infinity

Let’s partially instantiate Num just so we have something to play with.

instance Num Nat where
    Zero   + y = y
    Succ x + y = Succ (x + y)
    Zero   * y = Zero
    Succ x * y = y + (x * y)
    fromInteger 0 = Zero
    fromInteger n = Succ (fromInteger (n-1))

We wish to construct this function:

search :: (Nat -> Bool) -> Maybe Nat

Which returns a Nat satisfying the criterion if there is one, otherwise Nothing. We assume that the given criterion is total, that is, it always returns, even if it is given infinity. We’re not trying to solve the halting problem. :-)

Let’s try to write this in direct style:

search f | f Zero    = Just Zero
         | otherwise = Succ <$> search (f . Succ)

That is, if the predicate worked for Zero, then Zero is our guy. Otherwise, see if there is an x such that f (Succ x) matches the predicate, and if so, return Succ x. Make sense?

And it seems to work.

ghci> search (\x -> x + 1 == 2)
Just (Succ Zero)
ghci> search (\x -> x*x == 16)
Just (Succ (Succ (Succ (Succ Zero))))

Er, almost.

ghci> search (\x -> x*x == 15)
(infinite loop)

We want it to return Nothing in this last case. It’s no surprise that it didn’t — there is no condition under which search is capable of returning Nothing, that definition would pass if Maybe were defined data Maybe a = Just a.

It is not at all clear that it is even possible to get what we want. But one of Escardó’s insights showed that it is: make a variant of search that is allowed to lie.

-- lyingSearch f returns a Nat n such that f n, but if there is none, then
-- it returns a Nat anyway.
lyingSearch :: (Nat -> Bool) -> Nat
lyingSearch f | f Zero = Zero
              | otherwise = Succ (lyingSearch (f . Succ))

And then we can define our regular search in terms of it:

search' f | f possibleMatch = Just possibleMatch
          | otherwise       = Nothing
    where
    possibleMatch = lyingSearch f

Let’s try.

ghci> search' (\x -> x*x == 16)   -- as before
Just (Succ (Succ (Succ (Succ Zero))))
ghci> search' (\x -> x*x == 15)
Nothing

Woah! How the heck did it know that? Let’s see what happened.

let f = \x -> x*x == 15
lyingSearch f
0*0 /= 15
Succ (lyingSearch (f . Succ))
1*1 /= 15
Succ (Succ (lyingSearch (f . Succ . Succ)))
2*2 /= 15
...

That condition is never going to pass, so lyingSearch going to keep taking the Succ branch forever, thus returning infinity. Inspection of the definition of * reveals that infinity * infinity = infinity, and infinity differs from 15 once you peel off 15 Succs, thus f infinity = False.

With this example in mind, the correctness of search' is fairly apparent. Exercise for the readers who are smarter than me: prove it formally.

Since a proper Maybe-returning search is trivial to construct given one of these lying functions, the question becomes: for which data types can we implement a lying search function? It is a challenging but approachable exercise to show that it can be done for every recursive polynomial type, and I recommend it to anyone interested in the subject.

Hint: begin with a Search data type:

newtype Search a = S ((a -> Bool) -> a)

Implement its Functor instance, and then implement the following combinators:

searchUnit :: Search ()
searchEither :: Search a -> Search b -> Search (Either a b)
searchPair :: Search a -> Search b -> Search (a,b)
newtype Nu f = Roll { unroll :: f (Nu f) }
searchNu :: (forall a. Search a -> Search (f a)) -> Search (Nu f)

More Hint: is searchPair giving you trouble? To construct (a,b), first find a such that there exists a y that makes (a,y) match the predicate. Then construct b using your newly found a.

The aforementioned Cantor space is a recursive polynomial type, so we already have it’s search function.

type Cantor = Nu ((,) Bool)
searchCantor = searchNu (searchPair searchBool)

ghci> take 30 . show $ searchCantor (not . fst . unroll . snd . unroll)
"(True,(False,(True,(True,(True"

We can’t expect to construct a reasonable Search Integer. We could encode in the bits of an Integer the execution trace of a Turing machine, as in the proof of the undecidability of the Post correspondence problem. We could write a total function validTrace :: Integer -> Bool that returns True if and only if the given integer represents a valid trace that ends in a halting state. And we could also write a function initialState :: Integer -> MachineState that extracts the first state of the machine. Then the function \machine -> searchInteger (\x -> initialState x == machine && validTrace x) would solve the halting problem.

The reason this argument doesn’t work for Nat is because the validTrace function would loop on infinity, thus violating the precondition that our predicates must be total.

I hear the following question begging to be explored next: are there any searchable types that are not recursive polynomials?

Did you like this post? Flattr this

Follow

Get every new post delivered to your Inbox.

Join 27 other followers