Nov 4, 2016

Nana

NANA is what I called him, but to the world he is the late Lutful Quadir Chowdhury, a well-loved husband, father, grandfather, prominent in the respect he earned from his large extended family, and a highly-regarded elder statesman of the South Asian banking community. For a time he settled down and raised his family in then-West Pakistan, but when the time came he chose to migrate to the newly-formed Bangladesh.

My Nana was a foundational rock of my childhood in Dhaka. To me his spacious home compound, with its large bungalow, lush green back lawn, and giant driveway with two garages at opposite ends, were my personal domain to explore and play in. I have many happy hours of running, jumping, cycling, cricket, soccer, badminton, carrom-board, Monopoly ... and every other childhood activity there. I remember monsoon seasons when we would bring the storm shutters down and the family would gather for tea and watch the rain pour down outside through the wall-to-wall balcony windows. Hours and hours of poring through his rooms and shelves filled to bursting with books. To this day I have dreams that are set in that house.

Nana was a collector of knick-knacks that any hipster today would give his right arm for. Hand-powered ice-cream makers, spotless Swiss food processor sets, a video cassette recorder that he would bring out to keep me entertained, a slide rule he gave me when I showed signs of interest in math ... but books got the pride of place in his home. They were proudly displayed on his shelves, kept in storage in room after room, kept near his side of the bed for easy access. I would spend hours entranced by those books. Every subject you can think of, from Greek mythology to Somerset Maugham, O. Henry (The Gift of the Magi) to Khushwant Singh. I, a small child, absorbed as much of them as he would lend me, like a sponge. They awakened my interest in chess, algebra, calculus, mythology, history, essays, poetry, ... the world.

He would take me for fun-filled trips to the video cassette rental store, treat us out to fast food, order in food whenever we visited (we accidentally got cuttlefish once instead of his order of cutlets), show me how he recorded his expenses in his ledger, and all the while carry out his responsibilities as a busy man even after retirement.

He would receive many visitors, whether friends,  family, or others; to some he would give the help or advice they sought; with others he would enjoy a few rounds of chess; and from others he would procure various services: palm tree tappers, snake charmers, gardeners, hairdressers....

He would make the rounds of his home every evening, one of his well-loved flashlights in hand, checking that all windows were securely fastened, all doors were locked and bolted shut, and that all of his household were accounted for. He would discourage anyone from leaving the house after nightfall, and be up again in the early morning, making sure everyone was awake. I've never been a morning person, and he always had to spend quite a lot of time convincing me to wake up.

I think Nana, coming from a zamindari (landowning) family that lost much of its wealth to the turbulent times, had an idea in his mind of what his life should be as a patriarch of his family, and he made that a reality through sheer hard work and persistence. He created an evergreen world, a perfect world for a childhood.

In the years after that, I was away from Bangladesh most of the time. I didn't get the chance or take the opportunity to see Nana as much as I should have. For years I kept telling myself I would meet him again and we would have another game of chess. Earlier this year I finally saw him and we had our game. I told him I would come back and we would have a rematch, and he agreed. I told him my younger brother would visit him soon, and he was glad to hear it. It gave him something to look forward to. I'm so grateful I was able to keep at least one promise.

After his passing, my overwhelming feeling is gratitude that I knew him.

Oct 16, 2016

The Birkana hexadecimal number symbols

AMONG number systems, the hexadecimal system of counting (or 'radix') has a special place in the hearts of programmers, being closely related to binary, the fundamental number system used by all modern computers. Unlike decimal, which counts ten numbers (0 through 9) before having to add a 'place' (an order of magnitude), hexadecimal allows us to count sixteen numbers (0 through 9, then A through F) before having to add a place.

While the hexadecimal notation of using the first six letters of the alphabet is practical in a rough-and-ready sort of way, no one ever accused it of being elegant. There does, however, exist a fairly elegant (and I think clever) notation for writing hexadecimal--it's called Birkana. The only problem with Birkana is that most of the internet seems to have forgotten about it.

Well, almost all. I obviously came across Birkana somewhere on the internet at some point, years ago. And there may well be many posts written about it in the back reaches of the Google search engine. But to this day, the only result I've managed to find in my searches has been a mailing list post in the discussions of The International Slide Rule Group--probably not a very prominent corner of the online world.

That's too bad, because Birkana is pretty cool and it does deserve a proper introduction. So, what is it exactly?

Birkana is a Runic symbol set for expressing the hexadecimal number radix, but it's designed in such a way that the exact shape of each number rune is built by combining a basic shape for the number zero and accents which correspond to the numbers 1, 2, 4, and 8. In the right combinations, they can express any number from 0 to F. Here are the shapes for the 'building block' numbers:

0x0

0x1

0x2

0x4

0x8

As you can see, every combination of the zero line and the accents will give us a hexadecimal number (between 0 and F). I find it easiest to sum up starting at the highest possible number, then adding on the next-highest number, and so on. Some examples:

0x3 (= 0x2 + 0x1)

0x6 (= 0x4 + 0x2)

0x9 (= 0x8 + 0x1)

0xD (= 0x8 + 0x4 + 0x1)

0xF (= 0x8 + 0x4 + 0x2 + 0x1)

Notice also the exact positions of the accents--they intersect with the zero line at either the top, middle, or bottom, and they end up parallel to exactly a quarter of the way up or down the zero line. The design may have been inspired by ancient runes, but it is very carefully thought-out.

Unfortunately, at the moment it's not practical to type in Birkana in any digital format. Theoretically, the Unicode Consortium could decide to add the Birkana symbols to the Unicode specification and some enterprising font designer could come up with a set for general use. Until then, you're unlikely to come across Birkana symbols on the internet. So for now, enjoy them here, and feel free to copy the SVG shapes off this page's source.

Feb 8, 2016

The Essence of Phantom Types in Scala

The phantom of the type opera

HEIKO Seeberger over at the Codecentric blog published an interesting post about using Scala's typelevel programming to encode phantom types in a strict way so that you could tightly control the types that are allowed to be phantasmal.

For example, if you have a hacker: Hacker[Decaffeinated], and you call hacker.hackOn, you want a compile-time error saying essentially that a decaffeinated hacker can't code on.

Heiko's techniques make some tradeoffs:

  • Having to encode the methods' phantom type requirements as type bound sandwiches or implicit evidence of types. This is required if we want to keep using object-oriented method call syntax.
  • Having to bound the Hacker's phantom type parameter to an explicit hierarchy of allowed phantom types, i.e. either State or its subtypes Caffeinated, Decaffeinated. I believe this is unnecessary, as the Hacker constructor is private and the companion object provides smart constructors that allow you to get only a Hacker[State.Caffeinated] or a Hacker[State.Decaffeinated].

If we trade away the object-oriented syntax, and give up the unnecessary phantom type hierarchy, we get:

class Hacker[S] private () /* 1 */

object Hacker {
  trait Decaffeinated /* 4 */
  trait Caffeinated /* 5 */

  val caffeinated: Hacker[Caffeinated] = new Hacker /* 7 */
  val decaffeinated: Hacker[Decaffeinated] =
    new Hacker /* 8 */

  def hackOn( /* 10 */
    hacker: Hacker[Caffeinated]): Hacker[Decaffeinated] = {
    println("Hacking, hacking, hacking!")
    decaffeinated /* 12 */
  }

  def drinkCoffee( /* 15 */
    hacker: Hacker[Decaffeinated]): Hacker[Caffeinated] = {
    println("Slurp...")
    caffeinated /* 18 */
  }
}

In this version, a few things are going on. By line number:

1
We make the phantom type parameter unbound and invariant, because we made the constructor private. Client code can't create any Hackers, it can only use the ones we provide. Also, we move all the logic out of the class body and into the companion object.
4, 5
We don't need a phantom type hierarchy, or even to seal the traits, because again client code can only use the Hackers that we provide, and the phantom type parameter is, as mentioned, invariant. Also, I don't put the states inside their own companion object because they're merely incidental to the main logic; they don't have any logic dedicated to them.
7, 8
We provide the smart constructors here. Note that the constructors don't need to be methods; they can just be values because these values are immutable. So operations on them can just keep reusing the same values.
10, 15
We make the hackOn and drinkCoffee methods both take and return a Hacker with the correct phantom type to explicitly show the transitions Hacker[Caffeinated] => Hacker[Decaffeinated] and Hacker[Decaffeinated] => Hacker[Caffeinated].
12, 18
We use our own smart constructors internally to separate interface from implementation as much as possible.

With the above code, we can get the highly desirable 'type mismatch' error that immediately tells us what's wrong:

scala> Hacker drinkCoffee Hacker.caffeinated
<console>:8: error: type mismatch;
 found   : Hacker[Hacker.Caffeinated]
 required: Hacker[Hacker.Decaffeinated]
              Hacker drinkCoffee Hacker.caffeinated
                                        ^

scala> Hacker hackOn (Hacker hackOn (Hacker drinkCoffee Hacker.decaffeinated))
<console>:8: error: type mismatch;
 found   : Hacker[Hacker.Decaffeinated]
 required: Hacker[Hacker.Caffeinated]
              Hacker hackOn (Hacker hackOn (Hacker drinkCoffee Hacker.decaffeinated))
                                    ^

Admittedly, we've given up object-oriented syntax to get here. But I personally think the tradeoff is worth it.