Reversing a list in Haskell

Totally bored and jobless over this surprisingly silent weekend, I decided to revisit some of the Haskell programs that I had written when I took the Functional programming course during the previous year. While I was at it, I remembered this particular topic which struck me as interesting back then (..and it still is). So I am going to write about it despite the fact that it is something that would be covered by any basic Haskell textbook or tutorial. Well, that just goes to show how jobless I am!

The first time we were asked to reverse a list in Haskell, I did it using the extremely straightforward method I could think of.

revList :: [a] -> [a]
revList [] = []
revList (x:xs) = (revList xs) ++ [x]

What we are doing here is, given a list of the form (x:xs) where x is the element at the head of the list and xs is the tail of the list (which is again a list!). We recursively apply revList to the tail and then concatenate the result with the singleton list containing the head x.

Turns out this really bad way of reversing a list.

Let us analyse why.

One of the ways of looking at a Haskell list, say [x,y,z,w] is
x:(y:(z:(w:[]))), reflecting the head:tail pattern mentioned earlier.

Observe that to append the element x at the end of the reversed list, we concatenate the reversed list with the singleton list [x]. Now, the concatenation of two lists even in Haskell is at best a linear time operation. One could think of a way of concatenating lists as follows

(++) :: [a] -> [a] -> [a]
(++) [] l = l
(++) (x:xs) l = x:((++ ) xs l)

Thus the concatenation operation would have to walk to through the first list at least once.

Let T_{rev}(n) represent the time taken to reverse the list of n  elements. Clearly T_{rev}(0) = 0. And suppose T_{concat}(n_1, n_2) = n_1 represent the time taken to concatenate two lists where the size of the first list is n_1 and the size of the second list is  n_2. From the code, we can set up the following equation:

T_{rev}(n) = T_{rev}(n-1) + T_{concat}(n-1,1)
T_{rev}(n) = T_{rev}(n-1) + n-1 which solves to
T_{rev}(n) = \frac{(n-1)(n-2)}{2}

Thus T_{rev}(n) is quadratic in n. This is hardly the time complexity we would have liked!

The reason for this is the fact that appending a single element to a list takes linear time proportional to the length of the list. This is due to the manner in which lists are internally represented in Haskell.

However, adding an element to the head of the list is a constant time operation. The code for doing this would look something like:

add_to_head :: Int -> [Int] -> [Int]
add_to_head x l = (x:l)

Thus, given a list (x:(y:(z:(w:[])))) appending, say an element v to the head would amount to storing the list as v:(x:(y:(z:(w:[])))). Thus we don’t have to worry about the length of the list. In this sense, the Haskell list is similar to a stack. Adding an element to the top or removing an element from the top is a constant time operation. But adding to the bottom requires popping out all the elements, pushing this new element, and pushing all the elements (ok, lists do better than that.)

So, we can make use of this fact to optimize revList so that the operation takes linear time proportional to the length of the list. And the optimization would involve same trick that is used in reversing a stack. i.e pop out the element at head of the stack, push it into another stack, and repeat this till the first stack is empty. This requires only linear time.

listRevFast :: [a] -> [a]
listRevFast l = _listRevFast l []
    where
        _listRevFast :: [a] -> [a] -> [a]
        _listRevFast [] l = l
        _listRevFast (x:xs) l = _listRevFast xs (x:l)

And this one, you can verify requires linear time since it accesses each element of the original list exactly once.

Posted in academia, geek, grad school, programming, tech | Tagged , , , | Leave a comment

Fun with Limit languages

Given an alphabet \Sigma the set of all finite words over \Sigma is denoted by \Sigma^{*}. The set of all infinite words over \Sigma is denoted by \Sigma^{\omega}.

For any infinite word \sigma let {\it pref}(\sigma) denote the set of all prefixes of \sigma.

For a language L \subseteq \Sigma^{*}, we define the Limit Language of L to be the subset of \Sigma^{\omega} defined as \hat{L} = \{\sigma | {\it pref}(\sigma) \cap L \text{ is an infinite set} \}

Thus for each infinite word \sigma in L^{'}, there is a totally ordered (with respect to the prefix ordering) infinite subset S_{\sigma} of L.

Let us look at an infinite language L^{'} over the alphabet \Sigma = \{a, b\} where L^{'} = \{\sigma | \sigma \text{ has finitely many b's} \}

The question we are interested in is , can this L^{'} be the limit language of some language L?

For now, let us assume that there is such a language L \subseteq \Sigma^{*} whose limit language is L^{'}. Following the notation set up earlier,  L^{'} = \hat{L}.

Note that any word in L^{'} can be viewed as some finite word over \Sigma suffixed with infinite number of a‘s. And so, we can write L^{'} = \Sigma^{*}a^{\omega}.
It follows that for every x \in \Sigma^{*}, we have xa^{\omega} \in L^{'}. Since L^{'} is also a limit language, there are infinitely many prefixes of xa^{\omega} in L. This implies that we can always find an integer n such that xa^{n} \in L.

Using this principle, we see that if x=b, then we can find a n_0 such that ba^{n_0} \in L. Now for x = ba^{n_0} b we can find a n_1 such that ba^{n_0} ba^{n_1} \in L. We can similarly find n_3, n_4, n_5, \ldots such that each prefix of the form ba^{n_0} ba^{n_1} \ldots ba^{n_i}  of the infinite string \sigma^{'} = ba^{n_0} ba^{n_1}ba^{n_2}ba^{n_3} \ldots is in L. Thus infinitely many prefixes of \sigma^{'} are in L.

[The notation setup below is only to satisfy my urge to make the aforementioned argument slightly more formal. And in the process make it unreadable. It can be safely skipped :P ]

For every x \in \Sigma^{*}, define
\mathbf{GoodSuffix}(x) = a^{n} where n is the smallest natural number such that xa^{n} \in L

Let

  • y_0 = b
  • z_i = \mathbf{GoodSuffix}(y_i) and
  • y_{i+1} = y_i z_i b.

Now consider the infinite string \sigma^{'} = b z_0 b z_1 b z_2 \ldots

We note that y_i z_i \in {\it pref}(\sigma^{'}) \forall i \in \mathbb{N}
By construction, y_i z_i \in L, \forall i \in \mathbb{N}
Hence {\it pref}(\sigma^{'}) \cap L is an infinite set.

The \sigma^{'} thus constructed is in \hat{L}. Since \sigma^{'} has infinitely many bs, it is not in L^{'}. But this implies that L^{'} \ne \hat{L} contradicting our assumption.

Since L is any arbitrary language, L^{'} cannot be the limit language for any L \subseteq \Sigma^{*}.

In a subsequent post, we shall see how this particular set L^{'} acts as an evidence in distinguishing between a particular class of Non-Deterministic Automata over infinite words from the corresponding class of Deterministic Automata over infinite words.

Posted in academia, automata, geek, logic | Tagged , | Leave a comment

Test post

Trying out a desktop client for blogs. The thing is for the past few months, though I have been writing quite a bit, I haven’t been posting enough since I am too lazy to go to the wordpress site and copy paste and format the whole thing.

Hopefully a desktop client will help me get around these issues.

Posted in Uncategorized | Leave a comment

Freedom from browser

So, this wild idea struck me yesterday when I was trying to set up Thunderbird for my college email account.

As of today, my primary personal email is Gmail, my feed reader is Google reader, my calender is Google calender, I use the Tweetdeck on chrome to post and read twitter messages. It seems like I am so dependent on the browser. May be that’s exactly what companies like Google wants. Have all the data in some cloud somewhere, and allow access to them through the browser through plugins or apps.

Is it possible to use the browser only to browse the Internet ? I mean, are there alternatives to these applications that can compete with or do better than the services that I use on the browser.

From today, I have decided that I am going to use Thunderbird for my personal mails as well. As for the feed reader, I have installed Liferea. I am using Blogilo to post my blogposts and I have decided to use Evolution for calendering.

Though I must admit, Thunderbird’s interface can in no sense be compared to the intuitive interface that GMail provides. And Liferea, though good for reading the feeds themselves, does not provide any means to share posts with friends or read friends’ recommendations.

Blogilo seems fine for now. Even the \LaTeX support seems to work just fine. However, I need to check if there’s an easy way to write code snippets.

And as for twitter, I am yet to find something that’s as nice as Tweetdeck. Seriously when ubuntu thought of packaging gwibber as the default client, I don’t know what were they thinking. Everything else seems bad. So for now, I have decided to stick with tweetdeck. However, if you know of alternatives, let me know!

Update: Thunderbird is truly what my mentor at IBM called "Thundercrap". So is evolution. Both of them are totally unfit on netbook. Once in a while they generate so much disk activity that the whole world comes to a stand still. I am trying out Kmail now. It’s not as bad, but it’s not so good either. May be I should invest a day on Mutt and learn how to set up multiple accounts

Liferea is good, but Akregator is better. Again takes lesser time to load. But both these aggregators seem to take ages to fetch the feeds.

Posted in FOSS, geek, tech | Tagged , , , , , , , | 1 Comment

Latex Test

Again, does \LaTeX work from Blogilo ? Turns out, it does!

Posted in Uncategorized | Leave a comment

Repressed and Rebels : Part 2

One of the advantages (or disadvantages, depends on how you see it) of the life as a grad student is the ample amount that’s available to waste away. Being a grad student, I make really good use of this opportunity to waste time. So much that I fear I might end up becoming a slacker one day.

And like any other campus in the country, the one where I study has a good collection of movies and TV series floating around. When I am not attending classes or breaking my head over assignments,  I try to entertain myself watching movies and Television series. Not that I have been very successful at this attempt!

Anyway, coming to TV series, there used to be this UK sitcom named “Coupling” which I liked very much. The first three seasons were brilliant. Not just the characters, the style in which the episodes were narrated were also awesome.  I didn’t like the fourth one so much. And from what I could gather, many others who have seen it haven’t liked it as much as they liked the earlier one. May be that’s why makers of the show decided to wind it up.

Now, one of the characters, which in my opinion was the highlight of the series was that of Jeffrey Murdoch played by Richard Coyle. A very confused character who has always has a way of bringing arbit stuff on the table, even when the situation is seemingly tense.   Interestingly, Colye chose not to reprise his role as Jeff Murdoch in the fourth season, and hence they had to do away with that character. May be that’s also one of the reasons why the fourth season was not as much fun.

Anyway, I was wondering, why would Coyle choose not to continue playing a character which was so immensely popular? In a 2005 interview Coyle revealed his reasons:

“I was very keen that that character didn’t stick with me. It’s the kind of character that does. I’m an actor and I want to be an actor when I’m 60. It’s a lifelong process, why cut it off by boxing yourself into a little pigeon hole early on?” – Richard Coyle, 2005

Well, the fear of  typecasting! Reminds me of an old blogpost of mine where a friend expressed something similar :

“Dude, I don’t want to be defined by some one thing that I do in life. I’ve seen it happen before. You show your interest in something, and people around you create an image, associating you with that thing. And in course of time, you yourself accept that image, and feed it further. One fine day, when you discover something else which is “fun”, the same people tell you that the “fun” thing doesn’t fit your image or it’s extrapolations. And thus, you automatically become a member of the society’s “Repressed or Rebels Club”. The moment you let something define you, you are enslaved by an obligation to do well in that. Sometimes it happens without your knowledge. And you start thinking – ‘But this is what I wanted to do all the while! So I should be happy.’ Just that my idea of happiness isn’t preceded by conditionals.”

May be that’s one of the reasons why people don’t like being in one place for too long.

Posted in arbit | Tagged , , , | Leave a comment

Failed to Spot the RCU Bug

Ok, I have lost any rights I might have had regarding bragging about having worked on RCU.

I failed to spot this awesomely subtle bug!

http://paulmck.livejournal.com/27219.html

Needless to say, I am very embarrassed :(

Posted in arbit, geek, linux | Tagged , | Leave a comment