Tag Archive for 'Learning'

Functional Programming

Yesterday evening, I was present at Paris Hackers, a meetup for Hacker News enthusiasts — and a «hacker» in this context is not someone who breaks into software systems, but someone who is passionate beyond words about how software works. But the definition is vague, and that vagueness is part of my surprise.

We had a little chat on the topic of recent buzzwords — concepts that people were interested in, but not everyone understood. One of them was Functional Programming. The speaker asked who knew enough about it to explain to the others, and I naturally raised my hand: I was taught functional programming formally, I taught it myself, I implemented a functional programming language, and I am using functional programming professionally on a daily basis.

My surprise was that I was the only one. I had sort of assumed that a majority of «hackers» would know what functional programming is. I will have to revise that definition.

« Having Functions »

Functional programming itself has a definition problem: depending on whom you ask, you can get two different definitions on functional programming. One definition is what I would call pure functional programming, and the other is better summarized as « having functions »

Of course all languages have something they call «functions» but I strongly believe that there is a list of minimum requirements before you are allowed to say that.

  1. You should be able to define a FOOBAR anywhere. At global scope. Inside a class. Inside another function. Inside an expression. It can be an anonymous FOOBAR, or it can be given a name, depending on the situation.
  2. You should be able to store a FOOBAR in a variable, pass it as an argument to a function, and return it from a function. If your language is strongly typed, it should have an easily described type as well.

Replace FOOBAR with «integer» or «string» and you will notice that without these requirements one can hardly say a language «supports integers» or «supports strings» — what if you could not store integers in variables, or write string literals as part of expressions?

These requirements are called «having FOOBARs as first-class citizens» by the way. In C for instance, functions and arrays are second-class citizens, and integers are first-class citizens. In JavaScript, functions are a first-class citizen.

Allowing functions helps make a language a lot more expressive. Let’s think of a quick example: performing an HTTP request and displaying the result in a window. In pseudocode that looks shamefully like JavaScript code, it would look like this:

function display(url) {
  var page = http(url);
  return new Window(page);
}

This function has an obvious limitation: if it takes five seconds to load the data through HTTP, then the program will freeze for five seconds and only then display the window. A better solution would be to make the request asynchronous: a window in a «loading» state is returned immediately, and a background process takes care of the HTTP requests and fills the window with the contents once they have been received.

A clean way of encapsulating this would be to let the http function handle the asynchronous behavior. The calling code would only need to provide a description of what needs to be done once the contents have been received. There are two ways of doing this in an object-oriented world.

Object-oriented solution #1: inherit from an http request class.

class GetPageRequest extends HttpRequest {

  // We need to know what window to put the contents in
  function GetPage(window,url) {
    super(url);
    this.window = window;
  } 

  // Override this function to react to the data being received
  function onSuccess(page) {
    this.window.setContents(page);
  }
}

function display(url) {
  var window = new Window(loading);
  var request = new GetPageRequest(window,url);
  request.runAsynchronous();
  return window;
}

Object-oriented solution #2: implement an «HTTP success event handler» interface.

class OnReceivePage implements IHttpRequestSuccessHandler {

  // What window do we need to fill ?
  function OnReceivePage(window) {
    this.window = window;
  }

  // Handle success (as previous example)
  function onSuccess(page) {
    this.window.setContents(page);
  }
}

function display(url) {
  var window = new Window(loading);
  http(url, new OnReceivePage(window));
  return window;
}

Both solutions are quite long, because object-oriented solutions involve a certain amount of syntactic overhead. In both cases, the only code that is actually relevant to our work is the contents of the onSuccess function. What if the language allowed us to define that function directly, and passing it to the HTTP request without any syntactic fuss?

Functional solution #1: local function definition.

function display(url) {
  var window = new Window(loading);
  function onSuccess(page) { window.setContents(page); }
  http(url, onSuccess);
  return window;
}

In fact, why bother with giving the function a name? Its contents are obvious enough, so it would be shorter and cleaner to just passing it to the HTTP request without any name.

Functional solution #2: anonymous function definition, or «lambda»

function display(url) {
  var window = new Window(loading);
  http(url,function(page) { window.setContents(page); });
  return window;
}

The latter example is syntactically correct JavaScript code, by the way. As you can see, the code is both shorter and more readable than the class-based version. In general, using inheritance or interface implementation to define a single method is always significantly more wasteful that using an anonymous function.

There’s a third requiremend that I left unvoiced. Look back at the previous examples again. Notice how the class-based examples have to store the window object explicitly, but the functional versions use the variable directly? This is known as «closures» : when defining a function inside a function, the defined function actually carries with it all the variables that were present when it was defined. Functional languages always have closures, because any non-trivial operation you might wish to place in an anonymous function will involve accessing data that was present near the definition.

In summary: functional programming involves the ability to manipulate functions as you would manipulate any other data type (define anywhere, store, pass, return…) and allows writing more concise programs whenever you need to pass, store or return some behavior to be executed later.

Examples of functional languages:

  • JavaScript
  • Lisp (including Common Lisp, Scheme …)
  • ML (including SML, OCaml, F# …)
  • Haskell
  • Ruby
  • C#

Examples of near-functional languages:

  • PHP only supports lambdas and closures since 5.3, and closure syntax is suboptimal.
  • Python has 99% support, the only issue is that only one-line lambdas are allowed.
  • XSLT 2.0 has no anonymous functions, but is otherwise functional. I kid you not.

Examples of non-functional languages:

  • Java
  • C
  • C++

Pure Functional Programming

This is the other definition of «Functional Programming» that you can hear, and the confusion is understandable: languages that match definition #2 have long been the only examples of definition #1 as well.

The relevant concept is purity: can the impact of a function on the rest of the program be described only in terms of its return type, and can the impact of the rest of the program on the function be described only in terms of its arguments?

Consider the signature of an interface method:

public int frobnicate(Foo f);

There are many ways in which that function can affect the rest of the program:

  • It could call a global function to perform changes in the global state, such as altering a singleton, setting a global variable, printing data to the screen, sending data over a socket…
  • It could change member variables of the object it is called on.
  • It could call methods on its argument.
  • It could return a new value that is then used by the calling code.

There are also many ways in which the rest of the program could affect the behavior of the function:

  • It could depend on global variables to decide what it should do.
  • It could read global state (user input, files, sockets…)
  • It could access the data of the object it is called on.
  • It could access the data of its argument.

The entries marked in bold can be deduced from the method signature: having a return type means you want to return something, being non-static means you wish to read the state of the object you are called on, having an argument means you want to read data from that argument. The other entries are possible, but not readily apparent in the signature.

Pure functional programming is the principle of least surprise: sure, those entries that are not in bold are possible, but it would be surprising if they happened, so they are in fact not allowed. A pure function can only read data from its arguments and can only write data by returning it.

Also, pure functions imply that data is immutable — if functions are not allowed to change anything, then they are not allowed to change data structures, so the data structures are by definition immutable.

By the way, pure functional programming is all about what you cannot do — so you could in theory write functional programming in any language just by following coding conventions to that end. In practice, immutability is quite hard to respect if there is no syntax for making it easier — you spend a lot of time creating manual copies of objects in order to change a single field.

Working with pure functions and immutable data structures involves both benefits and trade-offs when compared to non-pure programing. Think of it as a slider which goes between «0% Pure» and «100% Pure» and you pick one value for your entire program. Many algorithms and concepts get easier to understand, change and manipulate as the slider moves towards the 100% end, but there are some concepts that are intrinsically non-pure and actually get harder and harder to think about as your slider moves away from the 0% end. For instance, working with a persistent data store is an intrinsically mutable endeavor, and it’s hard (but possible) to think about it in pure terms.

I find that a slider value of 95% in a language that makes such a value possible is the optimal place to be — the 5% includes writing code that is truly non-pure (such as database manipulation, responding to HTTP requests…) as well as code that is non-pure on the inside but is actually pure from the outside (such as memoization and caching).

Article Image © Tim Olson — Flickr

RS Latches


One of my oldest memories harkens back to 1989 — I was a four years old boy in communist Romania. My mother has a PhD in biochemistry, and her father and brother both had a PhD in physics, so it might seem quite unsurprising that I followed in their rational and scientific steps, but it would be hard to put the proverbial finger on how, precisely, that happened. This is what that specific memory is about.

It all started with my frequent stays at my grandparents’ house, a conventional second-floor flat in Bucharest, where my grandmother and grandfather took turns babysitting me while my parents were out hammer-and-sickling (well, laboratory-and-architecturing) the socialist ideal. My grandfather was intent on turning me into a bright scientific mind, so he asked my uncle to build me a computer. Nothing fancy, mind you : it had no operating system worth mentioning, no hard drive, and depended on magnetic tapes and 8″ floppies to actually work. My grandfather showed me a standard BASIC interpreter, and had me type in a program that displayed, line by line, an analog wall clock.

Fascinated, I started spending my days on that thing writing BASIC code, learning how to build increasingly complex programs, and starting my career as a programmer. Or so had my grandfather hoped. A few seconds after discovering computer programming, I discovered computer games, which were a far more fascinating novelty than displaying wall clocks on a screen. I promptly forgot about the BASIC interpreter and for nine long years, I assumed that programming computers was some sort of esoteric arcane art, invisible to the uninitiated, and remained entirely uninterested in it.

Instead, my breakthrough as a rational mind was triggered by the close proximity of two unlikely catalysts : one was a frequent diet of mecha anime (the quality of the Romanian dubbing was hilarious), and the other was a cupboard drawer full of bits and pieces that could, to a child’s mind, be spare parts out of which a robot could be built : wheels, small electrical engines, cables, batteries, microprocessors, light bulbs… as a matter of fact, once I had the basic understanding of how a batteries + cables + engine setup worked, I did build small uninteresting contraptions.

I became intensely interested in building a robot myself. Obviously, I did not have the technical skills or the willpower to follow through with this plan, but I would listen, entranced, to any explanations I would receive that were related to robot-building. My grandfather was writing a book on semiconductors at the time, so he showed me a large digital circuit and let me understand that this is what the brain of a robot would look like — only quite larger !

And so he started teaching me the elementary principles of digital circuits. We spent little time discussing the underlying technical details, and instead concentrated on the simpler abstractions of logical gates. This time, I was fascinated. I would grab a pen and paper and draw circuits for fun. The meaning of AND, OR, NOT, NAND, NOR and XOR are imprinted in my brain ever since I was five years old… there are few concepts remaining in my brain that have been there for so long.

My circuits behaved like mathematical functions : I would mentally set the input bits, and the output bits would contain the result, so I could build the truth tables that mapped input combinations to output combinations. I experimented with basic arithmetic functions, learning binary as I went. And then one day my grandfather showed me a circuit that I could draw from memory to this day : the RS latch.

The fun thing about the RS latch is that it cannot have a truth table. It is an entirely different beast from arithmetic “write input bits, read output bits” circuits in that it has a state. If you write 1 to the S input bit, the output becomes 1 and remains 1 until you write 1 to the R bit, at which point the output becomes 0, and so on. To say things differently, the S input bit stands for “Set” and sets the output to 1, and the R input bit stands for “Reset” and sets the output to 0. When both R and S are set to 0, then the latch output bit is equal to whatever it was previously set to.

The RS latch is a versatile little thing. It can be used to implement RAM (one of the first things I did with it), or it can be chained to create an incrementing counter.

After a while, my interest in digital circuits faded, but the effects it had on my character were permanent : I now had experience applying abstract rules to abstract concepts, and it was fun.

Article image © Cornelia Kopp — Flickr

99 OCaml Problems

I find that when learning the basics of a new functional language, or introducing oneself to functional programming in general, the 99 Lisp Problems are a good start. You don’t have to run through all of them, but how fast you can solve them says a lot about your fluency in the language, and has many things to teach even to otherwise experienced programmers.

I’ve started committing solutions to those 99 problems in the Objective Caml language to GitHub ; the repository is:

https://github.com/VictorNicollet/99-Problems-OCaml

If you’re interested in starting OCaml programming, have read the manual, and are looking for exercises to get up to speed, consider spending a little time trying to come up with the solutions on your own, using my solutions as a reference. And if you’re an OCaml expert, feel free to propose corrections and improvements : this is what GitHub is for.

Other solutions for OCaml do exist, for instance from Christian Kissig, which is currently more complete than mine. Note that we don’t share the same philosophy as far as writing the code goes, so you can probably look at both sides of the issues. For example, on the “find the last element of a list” problem, Christian throws an exception if no last element exists, while I return None, because I hate exceptions.

Enjoy.

Object-Oriented For the Win.

Readers, beware: this is an opinionated piece. Feel free to curse appropriately in the comments below, should you find the need to do so. I’m writing this because of yet another encounter with an object-oriented zombie, and one without the excuse of being fresh out of school. They all stand united behind the motto that Object-oriented programming makes your code easy to reuse, debug, maintain and extend and I happen to disagree.

Something interesting happened in the Pacific Ocean after World War II: during the war, American soldiers had set up air strips on Pacific islands, complete with little control towers that had radio stations. And the natives observed that those soldiers would speak into a weird piece of metal, and a giant iron bird would land from the sky and deliver food and supplies. Then, the war ended, the soldiers went home, and the natives tried to bring the giant iron birds back by building shacks that looked like legitimate control towers, and spoke strange words into rocks that looked like legitimate microphones, and it worked!

No, it didn’t. Cargo planes did not come back because it was not the shape of the microphone and antenna that brought in the planes, it was their invisible electromagnetic properties. These are the cargo cults: imitating the outside appearance of things that work and expecting the imitation to work as well. The same happens with object-oriented programming — the use of classes, or inheritance, or design patterns is not the reason why good code is good: they are merely tools which happened to be applied by knowledgeable and skilled programmers in order to avoid problems that they knew would happen if they did not preempt their appearance. To look at their code, find out that they used classes, and deduce that classes were responsible for their success is about as rational as expecting to steal the strength of your defeated foe when you eat his flesh. Object-oriented programming can only solve design problems you know you need to solve.

Imagine a piece of old, spaghetti C code written in procedural style, with functions calling each other and accessing global variables all over the place. I suspect many young graduates these days never had to deal with these — and I wouldn’t have either, were it not for my unrequited love for mental anguish and programmer pain. Back to the point: in your mind, draw an arrow from A to B if function B calls function A or accesses global variable A. This is a dependency graph: if you were to change the run-time behavior of A, then the behavior of B would almost certainly change as well. By following all outgoing arrows from the point you altered, you can find every element that could possibly be affected by it.

No programming style or design methodology on earth is going to change this ; whether object-oriented or aspect-oriented or functional, functions call other functions, and changing one part will have an impact on many other parts. That is something we accept, because propagating changes is part of the programming job, and we have even elevated refactoring — the propagation of the absence of changes — to the level of a good thing since sliced bread.

And since we have to track down all the dependencies of a given entity sooner or later, our national sport is to make it as easy as possible. One way is to let the compiler or build process help — compilers detect type mismatches that are usually a hint of non-propagated major behavior changes, while automated unit tests and regression tests handle more subtle changes, and both of these are fairly independent of your programming style. Another way is to willingly reduce the number of dependencies through architectural constraints — Model-View-Controller prevents a model from being dependent on a controller, because altering a controller should not change the behavior of a model. These are fairly common ways to reduce static dependencies.

Then, there are the dynamic dependencies — functions which alter the behavior of other functions at run-time. Remember those global variables from the C program? If function A writes to the global variable and function B reads from the global variable, then calling A will probably change the behavior of B. Runtime dependencies are fairly obvious to map: every time a function writes to a global variable, draw an arrow from the function to the global variable and mark the function as having a side-effect. Then recursively do the same for every function that calls it, and so on until you run out of functions. Your dependency graph just became a lot hairier than it was before.

Such dependencies are the reason why working on the report-printing feature in your invoicing software somehow managed to break the database storage : even though both modules are independent and the static dependency tree for report-printing does not flow into the static dependency tree for database storage, there are a handful of global variables that allow your changes to follow dynamic dependencies and leave a flag unset when it should have been set and ultimately blow up the nuclear silo.

So, when you have global mutable state, then changes can jump from module to module through those pieces of global state. Procedural programming mostly dealt with this by cleanly wrapping up any global state in a module, and having modules interact with each other by means of interfaces that managed to guarantee some invariants on the global state. But still, some problems remained. I am reminded here of the code to Dungeon Crawl, an open-source game written in procedural style, where the module responsible for dealing damage to the player will make frequent calls to the module responsible for outputting messages about the damage being dealt (“The hobgoblin hits you!”). As written, you cannot use the damage-dealing code without displaying messages, so writing an AI module that tries to predict the outcome of an attack is harder than it seems, because it cannot use the existing damage-dealing code to run predictions.

They actually have sludge elves.

Functional programming solved the global mutable state issue by eliminating global mutable state altogether. In the aforementioned example, the damage-dealing module would return the new damaged player along with a list of messages that were generated, and these messages could then be discarded silently in the AI subroutine, or forwarded to the screen in the main routine. I am a big fan of functional programming, but let’s face it: not only is it harder on the brain than good old set-variable-values-everywhere programming, but it does not suit well to situations which have an implicit reliance on global mutable state — such as web servers connected to a persistent database. I look forward to a pure functional friendly database, but it’s not there yet.

Both of these solutions rely on encapsulation: whatever happens to be the implementation of a procedural or pure functional module is hidden, and only available through those functions. This creates a dependency bottleneck, so any changes performed within the implementation can only leak out through the interface in tightly controlled ways — at compile-time, those are called contracts, at run-time they are called invariants.

Object-oriented programming works by deprecating global mutable state. It’s not completely gone, and some programmers yearning for the good old days still try to enjoy some global goodness by using the Gang of Four Singleton pattern, but it’s mostly deprecated. The sickle and hammer of object-oriented programming are dependency injection and late binding, and it uses them to break down the structure of static dependency graph bourgeoisie.

Yes, object-oriented programming is all about building the dependency graph at run-time. Then again, a program that generates machine code at run-time does the same. Object-oriented programming merely provides a set of tools that are easier on the human brain than the extremes of generating machine code at run-time. As an aside, keep in mind that it is not the only toolbox available to you: any language with closures can do the same, and although closures are both more elegant and slightly more complex to handle in the general case, they have found their way into event-based programming because an event handler is just, well, a closure. This is why jQuery passes functions around everywhere instead of requiring the user to implement an IAjaxResultVisitor interface: it’s shorter, but still fairly easy to understand in that context. If you push things far enough, most objects are usually nothing more than dictionaries of closures.

Back to the point: writing a proper object-oriented program with those tools is about the same as creating a statue out of stone using sculpting tools, and inheritance will not turn someone into an object expert any more than holding a chisel turns them into a mutant ninja turtle disambiguation page. How does it happen?

The original problem with procedural programming was that there was no easy way to unplug the damage-dealing module from the message-printing module. Dependency injection means that the damage-dealing module (which is now an object) does not know about the message-printing module (which is now also an object), instead, whoever needs to use damage-dealing code must provide it with a message-printing object that will be used to print whatever messages come up. That message-printing object might actually print those messages to the screen, or it might silently discard them, or it might keep them around and only display them to the screen if a specific event happens, or it might be an unit testing mock, or any other amount of different behaviors. In terms of dependency graphs, there is no static connection between damage-dealing and message-printing: the program decides at run-time what message-printing object should be bound to what damage-dealing object, and can create new objects on the fly should the situation require it.

Aside from that, there are no significant architectural benefits to using objects or classes — although touted as an object-oriented achievement, encapsulation is commonly available in functional and procedural programming as well, and using object.function() instead of function(object) is a matter of taste, not architecture.

As a final word, I am fairly doubtful of the ability of schools to teach their students about good object-oriented programming. They can certainly teach them how to use the tools, but the pains that object-oriented programming is meant to solve only become obvious when you have to work with a large, multi-developer project over a long duration and with changing requirements — anything less, and your pains will be subtle feelings of awkwardness instead. Definitely not something you can learn from. If you have never written an unmaintainable piece of mud, you cannot know how object-oriented programming can keep you from writing one.

You may now dish out punishments in the comment box below. Have fun.

Do Variant Types in OCaml Suck?

I recently stumbled once more on Tomasz Wegrzanowski’s blog, on one of the early articles he wrote in 2006 about Objective Caml — unequivocally titled Variant Types in OCaml Suck. Hence the title of this article.

Objective Caml polymorphic variants have the benefit of being created on the fly: you just write ` kitten and you have successfully created a value of type [> `kitten] (do note that you have also created a singleton type out of nothing — this can be quite useful in some cases). Of course, the ability to define types on the fly everywhere puts a strain on the type inference algorithm, who must then determine whether you are mistaken or not.

Type Inference : Damas-Milner

Type inference in ML language strives to determine the type of every value and variable in the code. It does so by giving every variable a completely general type, and then examining any constraints that apply to progressively turn it into the most general type that satisfies all constraints. Let’s try a quick example:

  • When you write fun x -> fst x + snd x, the type of x is initially 'x.
  • The type of fst is 'a * 'b -> 'a, which means that the type of x must have the shape 'a * 'b (because it’s provided as an argument to fst). So, the constraint implies that 'x = 'xa * 'xb (and that fst x is of type 'xa).
  • The type of operator + is int -> int -> int, from which the type of fst x is constrained to be 'xa = int and thus 'x = int * 'xb.
  • The type of snd is 'a * 'b -> 'b, but since 'b = int in the present context, this means that its actual type is 'a * int -> int and thus 'x = int * int

So, by applying constraints deduced from the code, the type inference algorithm computes the type of variable x. Applying a type constraint is known as unification: two types are determined to be equal, so they are superimposed on top of one another in order to construct a new unified type. This happened in the last step above: x had been determined to be of type int * 'b and this type was unified with type 'a * int. Unification is a simple pattern-matching exercise: one explores the two types as if they were trees, and…

  • If identical nodes are encountered (such as a _ * _ 2-tuple node or a leaf-less int basic type node), the unification proceeds recursively.
  • If a type variable (such as 'a or 'b) is encountered, it is declared equal to the corresponding element in the other type.
  • If two different nodes are encountered (such as a _ * _ constraint being unified with an int variable), an error happens.

Polymorphic Variant Types

Polymorphic variant types are lists of possible constructors. For instance, [`kitten | `walrus] represents a type that contains the constructors `kitten and `walrus.

When you write `kitten, the resulting type is [> `kitten]: an open variant type that can be unified with other variant types. Consider, for instance, the array [| `kitten ; `walrus |]: it is of type 'a array where 'a can be unified with both [> `kitten] and [> `walrus], which results in [> `kitten | `walrus].

Now, let’s consider the reverse operation: pattern matching. You write a simple match animal with `kitten -> "meow" | `walrus -> "bukkit": the type of `animal will be computed as [< `kitten | `walrus].

The difference between [< ..], [..] and [> ..] is obvious in terms of unification:

  • [< `a | `b | `c] can only be unified with variant types that contain less constructors than itself. So, it can be unified with [ `a | `b ] (which yields [ `a | `b ]) but not [ `a | `d ]. The reason is quite plain: if you were allowed to introduce `d into the variant type, then you could run the above match with animal = `owl and break the code. In short, [< ..] means “any others are forbidden”.
  • [> `a | `b | `c ] can only be unified with variant types that contain more constructors than itself (including other open types). So, it could be unified with [> `a | `d] (which yields [> `a | `b | `c | `d]) but not with [ `a | `b ] (which does not allow `c). In short, [> ..] means “these are allowed”.
  • [`a | `b] (a closed type) is both [< `a | `b] and [> `a | `b] at the same time. It can only be unified with variant types that allow those two but no others, and cannot be unified with any closed types other than itself.

This works, but it’s not perfect.

One major issue is the fact that every variable has a single type. So, suppose you want to transform `b into `c but leave any other constructors untouched. You would then write function `b -> `c | x -> x, but that would be a mistake: being present in the pattern matching means that x is of type [> `b] (it can accept any value, including `b) and being returned means it is unified with the type [> `c] of the other possible return value. So, the type of this function is actually ([> `b | `c] as 'a) -> 'a: even though you replaced every `b with a `c, the type inference insists that the result type can still contain a `b… In fact, there is no way to write such a function because there is no way to express the type of that function in Objective Caml.

Type Coercion

Another issue is that sometimes, you need unification between two different closed types. Consider this short example:

let string_of_vehicle : [`car | `train | `bike]       -> string = (* ... *)
let is_heavy       : [`car | `bike | `cake | `anvil ] -> bool   = (* ... *)

List.map (fun x -> if is_heavy x then string_of_vehicle x else "") [ `car ; `bike ]

This code should work, because I’m working on a car and a bike, both of which can be passed safely to both string_of_vehicle and is_heavy. However, due to external factors, the types of string_of_vehicle and is_heavy are closed and x has to unify with both. In such a situation, the solution in Objective Caml is to allow the user to make the conversion explicit by use of type coercion. In this example, it would look like this:

List.map (fun x ->
  if is_heavy (x :> [`car | `bike | `cake | `anvil ])
  then string_of_vehicle (x :> [`car | `train | `bike])
  else ""
) [ `car ; `bike ]

Coercion works by allowing a [<..] to be treated temporarily as a [..] — the solution above works by using two coercions to unify x as being of type [< `car | `bike], which is compatible with both types that it is coerced to. This is, for all purposes, merely an explicit way to convert a value from a type to a supertype (“any square is a rectangle”) that is not otherwise possible in the unification-based world of Objective Caml types — unification can only work with type equality, not with types being supertypes of other types.

Supertypes, and coercion, are intricately tied to loss of information. When you convert from [<`car | `bike] to [`car | `train | `bike], you are discarding the information that your value can not be a `train. While this loss of information might seem innocuous, it does prevent you from passing that same [<`car | `bike] for a [`car | `bike | `cake | `anvil], because the latter does not allow `train and you just discarded the information that `train cannot happen…

Since loss of information can be deadly to the soundness of a type inference algorithm, the Objective Caml design decision was that all loss of information (converting a type to a supertype) should happen explicitly (by means of a coercion).

Of course, coercion is only usually required if you have closed types in your program. Try avoiding them as much as you can, and you will find that you don’t actually need coercions all that often.

The Original Problem

Back to Tomasz Wegrzanowski’s issue: he was writing a compiler that needed to manipulate both scalars and vectors. So, he defined a value type:

type value = [`Scalar of float | `Vector of float * float * float]

He also defined specific types in order to ensure type-safety of some operations:

type scalar = [`Scalar of float ]
type vector = [`Vector of float * float * float]

type operation = [ `Muliply of scalar * scalar | `DotProduct of vector * vector ]

What he wanted to achieve was to extract all the values available within an operation:

let values : operation -> value list = function
| `Multiply (a,b) ->  [a;b]
| `DotProduct (a,b) -> [a;b]

Of course, this function is discarding precious type information about the values, which requires a type cast. The naive solution would be to individually type-cast a and b throughout the function, but this would be quite tedious. Instead, let’s strike at the root by coercing the function argument itself: by discarding information before the pattern matching occurs, we allow the code to compile with a single coercion. So, what do we coerce the argument to?

It’s not easy to tell. I guess I could create a copy of the operation type and replace all types with value, but that would be quite tedious. Instead, let’s rely on a simple property : when you need to coerce a value in order to pass it to a function, you need to coerce it to the type of that function argument. And the type of the function argument can be obtained through type-inference. Simply write this and compile it:

let values : 'a -> value list = function
| `Multiply (a,b) ->  [a;b]
| `DotProduct (a,b) -> [a;b]

let _ = values ()

The compiler determines the type of 'a through unification, knows that it’s not unit, and generates an error that describes the actual expected type. We can copy-paste it from the compiler output directly!

type general_operation = [ `Multiply of value * value | `DotProduct of value * value ]

let values x = match (a : operation :> general_operation) = with
| `Multiply (a,b) ->  [a;b]
| `DotProduct (a,b) -> [a;b]

let _ = values ()

Should the type operation change, an error will immediately happen in the definition of values (as the coercion from operation to general_operation would fail), which provides the new type that should be pasted on top of general_operation.

The Forces of Evil

Bad luck happens. There’s always an element of chance that you cannot control, no matter how many failsafes and backup plans you have.

A few years ago, my employer decided to move to new offices in downtown Paris. The power went out several times that week, as our new landlord ironed out the specifics of software engineers renting the space: our developement and CVS servers, and their air conditioning, used up a lot more power than the previous tenants.

For those of you unfamiliar with the software engineering world, the CVS server is the place where the source code is stored. You can live without it for a few hours, since you usually have a copy of whetever you’re working on stored on your own computer, but losing the data is the second worse thing that could happen to a software company (the first being that the entire development team gets hit by a bus).

Since the data was so critical, we had several layers of shielding to protect it. First, there was a daily backup. Second, weekly backups were kept for a year in a remote facility. Third, the data was stored on RAID drives, meaning that should one drive fail, it could be replaced without losing any data and without the users even noticing. Fourth, the RAID drives had their own backup battery power, so that they could finish writing whatever they were writing when the power went out. Fifth, there was a failsafe that prevented the drive from writing anything if the batteries were missing.

The bad news is that the failsafe did not work: the connector had been damaged during the move, and thought that batteries were present. The batteries were out of order, but the drives thought they were present, so they tried to finish writing the data, and ended up writing the correct data at the wrong location. These erroneous writes went unnoticed for a week, until people found C code showing up in Java source files. And by then, the daily backups were all corrupted. Oh, and the local copies several developers had kept were also corrupted.

We ended up using the previous weekly backup, losing several man-months in the process, and reapplying any modifications left on our computers.

Of course, we chose to move at a time where no critical deadlines were looming precisely because we were afraid something went wrong, so we could afford losing those man-months. We could reduce the impact of bad luck, but we couldn’t prevent it altogether.

Related Posts

Suicide Bomber Training Camp

When you’re doing something, there’s this nice equation that can help you determine whether you’ll be successful:

Chances of Failure = Forces of Evil – (Brains + Experience)

The Forces of Evil are constantly working towards your untimely demise. For instance, suppose you have an important meeting with your investors. Having spaghetti for lunch is a good way to get tomato sauce on your clean white shirt. You can predict this if you’re smart (brains), or you can know this because it’s already happened (experience).

The Italian Forces of Evil

The Italian Forces of Evil

Predicting potential issues is great. You get to avoid problems you have never encountered.

But there’s a limit to how many things you can predict, especially in a short amount of time. Geniuses who can predict everything and plan accordingly are the stuff of legends and fiction. By contrast, learning from experience is far more efficient: all you need is a good memory.

Besides, having experienced a problem first-hand lets you recognize a solution when you see it used by someone else. Have you ever noticed how hard it is to convince non-technical people of the benefits of source control when they’ve never had their documents overwritten by someone else?

While useful, learning from the mistakes of others is less efficient. You don’t have the searing, vivid memories of your own failure to drive the lesson home, and you don’t have a detailed recollection of all the little things that went wrong.

Sure, sometimes it’s hard to learn from your personal experience, especially when once-in-a-lifetime situations. The cost of trying again has a huge impact on how experienced you can become.

At one end of the spectrum, we have suicide bombers. They never get a second chance. At the other end, we have modern computer programmers. They can fail as many times as necessary, because it only takes an edit-rebuild-run cycle to try again. And the ideal place to be is…

…in the middle. Because there won’t be any searing, vivid memories of your failure if it can be overcome within three seconds.

All of you here have one hundred thousand bad drawings silly mistakes in you. The sooner you get rid of them, the better it will be for everyone.

Anonymous art institute instructor, quoted by Chuck Jones, adapted by me

Related Posts

Seven Steps for Fast Learning

Learning an entirely new concept does not happen overnight. On the other hand, there are ways you can follow to make it happen faster or avoid reaching a dead end. Here are seven simple, three-word steps you can follow:

1. Find someone knowledgeable. By this, I mean a real person that you can meet face-to-face or on the phone, not some random person on the internet or, worse, a manual. Then, ask them to talk about the topic. If you found someone who is passionate, they’ll throw a flurry of sentences at you that are probably way too complex for you to understand. Grasp what you can, ask questions if it helps, and don’t be afraid to come back later if you have more questions or need written references.

2. Write everything down. If you’re not familiar with a topic, you are bound to forget everything you hear or read. By writing things down, you are doing a second pass on your short-term, which helps you commit that to a longer term. And besides, you’ll have it in writing for future reference. Mind maps do help: they don’t contain a lot of details, but their graphical nature helps bring back detailed memories.

3. Unravel the threads. Any domain is like a web of related concepts. You ultimately need to understand all the major concepts and relationships, and you will learn a lot of minor details along the way. So, follow the links as often as you can: every word you hear, every concept you discover should be written down so that it can be explored later on. This is a good time to start looking for manuals: Wikipedia can do a fine job explaining the general idea, but you usually need more practical textbooks or courses for the finer details.

4. Never stop exploring. It can be tempting to decide that you understand a given concept. In fact, we do it all the time because we simply don’t have time to become an expert at anything. Think you know what a backorder is? There are probably many concepts you have never heard about, or never thought were relevant, that may completely change how you look at backorders if you take the time to examine them closely. Every new concept we discover can change the way we look at things we took for granted.

5. Try explaining it. Find an audience that is unfamiliar with the topic and make yourself understood. Participate in online forums and discussions on the subject (you might want to do it anonymously at first). Thinking of an explanation or practical application for your theoretical knowledge will highlight any grey areas you might overlook. Confronting human intelligences with your ideas follows the nothing ever goes according to plan theory, which forces you to look at the subject in a different light in order to communicate.

6. Sleep on it. When you keep a lot of concepts in short-term memory, it’s easy to forget what is right, what is wrong, and what is an outdated assumption. Flushing things out of your brain by sleeping or doing something else for a while will keep only whatever ended up in your long term memory. Then, you can go back and fill the holes through more thinking or reading, thus eliminating any inconsistencies as you find them.

7. Practice, practice, practice. No amount of reading or thinking about a topic will make you into an expert. The devil is in the details, and most teachers or resources take those details for granted… or left as an exercise to the reader. Do your homework: you can learn what? from books, but how? is something taught only by experience and why? is for you to meditate on.

How often do you get paradigm-shifted by a new discovery that changes everything you thought you knew about something? This once happened to me very often, but the frequency is starting to decrease. I must be getting close to knowing everything :)

Related Posts

Brain Dump

Programmer Fonts. We programmers love fonts that are fixed-width, clean and readable even with a small font size. My personal favorite is Proggy Tiny, a free programming font. Do you have your own favorite, or do you use whatever the system default is?

Stop Micromanagement. Take any game where you play as the here and have to accomplish something. Now, turn it into a game where you control the world to help the computer-controller hero accomplish the same thing. This is the difference between doing it yourself and micro-managing someone to do it.

Programming Games. On the topic of having games teach interesting concepts, the second installment of LightBot is now available on Armor Games ; the game teaches recursion, recursion-based loops, and conditionals.

Google Street Smarts. It’s fairly easy for us to search online for our own names, to see what others might find. How many of you have tried to search for pictures on geographical locations based on their names? And how can we know if we’re not on Google Street View, anyway?

New Favicon. There’s a new favicon on the blog. You should see it in the address or tab bars above, or here:

Copy-Paste Your Insight

I do improvisational theater. I’ve been doing it at an amateur level for three years now. My favourite exercise is to stand on stage, in front of an audience, and be given a word or sentence. Then, I have to spontaneously tell or act some kind of story revolving around that word or sentence, lasting exactly thirty seconds.

Like, someone says Asparagus and I’ll act a scene where I put on some boots, gloves and a radiation suit, open a fridge and complain about my spouse’s cooking.

119369226_596ada02e8

Of course, when you have to do something like this, you simply cannot plan in advance everything you are going to do before you start. In fact, you can’t even plan how it is going to end. You just don’t have time to think in that split second between the moment you hear the word and the moment you start acting. You have to start acting right away. So, choose an action and do it. Anything. You hear Asparagus and you start tying your shoes slowly because you just feel like it. This leaves you a few seconds to think about who your character is, and why he is taking that specific action.

Once you have a good character in mind, it’s easier to act in character, even without a clear objective. This leaves you with some time to choose that objective and decide how the act will end. You will spend about fifteen seconds looking for an idea, so you just have to have a character or you’ll be naked.

There are good characters and bad characters. A bad character is a noun. A policeman. A chef. An extraterrestrial. A lightbulb. A good character is a noun and an adjective. An allergic policeman. A sexy chef. A tax-evading extraterrestrial. An imaginary lightbulb. The adjective adds depth to the character : that’s where great acting and great ideas come from. In fact, the further apart you choose your noun and adjective, the greater the potential. A policeman whose defining characteristic is allergies is a lot more unusual than a policeman whose defining characteristic is strength.

This also works outside of improvisational theater. It is by combining ideas from different areas of life, in ways that seem completely crazy, that entire philosophies and ways of understanding emerge.

Applying insight you get from a certain area to another will improve your knowledge and understanding of the latter.

On the other hand, we’ve been incessantly told that analogies are a bad idea. Smart, credible people have determined that you need ten thousand hours to become an expert at anything. Movies show that you can’t just copy-paste your expertise as a fisherman to be a loving and caring father. An expert baseball coach, no matter how experienced, will never be able to understand nuclear physics by applying his baseball expertise.

The natural reaction of anyone is to take their experience from whatever area they are an expert in, and use it to improve their skill in a new area they are beginning to discover. This never works. You just end up with baseball loonies explaining quantum mechanics in terms of batting averages.

By definition, when applying your experience to an area you are unfamiliar with, you cannot tell if what you are doing is right or wrong.

On the other hand, learning about baseball might just give a quantum scientist that little nudge in the right direction to form a new theory or solve a difficult problem. The history of science is filled with epiphanies that came from completely unexpected directions.

So, stop thinking about your job all the time. Do something new, like baseball or fishing or improvisational theater or knitting or reading yaoi fanfics. And every time you see something new, ask yourself what it teaches about your own craft. When everyone around you does a good job, be the one who does an allergic job.

Related Posts



1150 feed subscribers
(readers who polled a feed this week)