Archive for December 2007

A visit to the golden prison

My wife managed to win an iPod Touch a the office Christmas party. I got more excited than her; she actually suggested we put it on eBay unopened, of course I simply had to open it and play a little. After a weekend I came to the conclusion that, to me, it was a piece of useless crap that we should try to sell ASAP. Luckily we managed to sell it on to someone who’s recently had a large sip of the Apple Kool-Aid. Here’s what I found out anyway, let’s start with the least bad.

The UI

It’s cute, very cute. Clicking icons, typing in the “keyboard” all very enjoyable. I tried out the zooming in Safari, beautiful. Then the cracks started showing, I can’t zoom everywhere, suggesting that it’s implemented on an application level. Why not provide that on a system level instead, so that all applications have it automatically? I also found it really irritating that there’s no copy-paste (apparently a common gripe). After I broke the jail of the 1.1 firmware and installed a audio cast client I had to use a pen and paper to copy URLs from Safari in order to subscribe. Poor!

Browsing the web

Getting network connectivity was a breeze. The UI of Safari is cute and the zoom is really handy. The first thing that irritated me was that there’s no way of saving things. Yes, there’s WiFi available in many large cities nowadays, but there’s still a lack of wireless connectivity outside of cities. So, my hope of being able to look for things while online and read while offline was a no-starter. I also would have liked to download videos and watch them later, on the other hand, and this is such a ridiculous mistake by Apple since it basically breaks the web, there’s no support for flash. Yes, the format that basically everybody uses to post videos online is not supported! Oh, but there’s YouTube you say? Well, on to that then…

The YouTube application

The only way of watching videos on YouTube is through this application. Surprisingly it’s not possible to use Safari to browse around using YouTube’s well-known web interface and find interesting things to watch that way. No flash support, remember?

On top of this there is no way of saving a video to watch it later. Again, listen Apple, there are areas that don’t have WiFi connectivity in the world!

Loading things on to the iPod Touch

I found this to be most disappointing. The only way to get stuff, music/video/audio cast, on to it one must use iTunes. There are rumours of support in bleeding edge libgpod, but by this time I didn’t bother with trying that out. What I did try was breaking the jail, installing OpenSSH, mounting it using SSHFS just to find out I only had read access in the versions of gtkpod/libgpod that’s in Debian Sid. Then I tried installing iTunes in WINE, but gave up after a few hours of trying to get that working. The next attempt was to use VMWare, using an evaluation license for Workstation I got as far as installing iTunes just to find out that it wouldn’t accept the iPod Touch when I plugged it into the USB port. After all of this, and my other findings, I didn’t think it’d be worth compiling libgpod from source.

Other bits and pieces

I’ve heard the calendar and contacts can only be synced to a Mac. Of course I couldn’t try it, since I don’t have a Mac.

The iTunes application on the device itselfi only contains just enough to spend money on the iTunes store. No way to subscribe to audio casts that I could findii.

Conclusions

I’ve never thought quite as much about the words “proprietary” and “technological silo” as I did while playing with the iPod Touch. The experience has put me off all Apple products, sure they are beautiful and cute, but to me they aren’t usable.

  1. I can’t remember if it were on there when I first opened it of if it only appeared after upgrading to firmware version 1.2.[back]
  2. I could always set up a personal audio cast containing my music had it been possible.[back]

A somewhat surprising catch

Let’s get straight to it. Here’s an example of something that I found somewhat surprising in Haskell. First a bit of setup:

printNum n = putStrLn $ "num: " ++ (show n)

handleE e = do
    putStrLn $ "Caught something: " ++ (show e)
    return (-1)

errorP = fromMaybe (error "Got Nothing")

And here it is, in ghci:

> CE.catch (return $ errorP Nothing ) handleE >>= printNum
num: *** Exception: Got Nothing

And to show that things are lazy we change handleE:

handleE e = do
    putStrLn $ "Caught something: " ++ (show e)
    return []

Then we can map errorP onto a list like this:

> CE.catch (return $ map errorP [Just 17, Just 42, Nothing, Just 666]) handleE
[17,42,*** Exception: Got Nothing

In neither cas I saw the behaviour I was expecting. A chat on IRC showed that others see this as natural behaviour, explained by laziness. It wasn’t until a night’s sleep that I realised that there still was something that bothered me about that explanation. Another explanation would be that catch isn’t special. At first I didn’t realise I expected it to be special; I expected it to somehow wrap the evaluation of its first argument so that no matter when it was evaluated any exception raised would be caught. As far as I can see this would be no small feat if laziness is to be preserved. It would require catch to be special.

So, what does this mean in practice? Well, here are my thoughts. One needs to think carefully about where using catch makes sense in a program. It has to be inside IO, a well-documented fact, but it also has to cover something that isn’t lazy since it then will have no effect at all. My gut feeling is that catch is useful “in the large”, with that I mean as a sort of catch-all “high up” in the program, e.g. in main. That means its usefulness in libraries is limited (except for IO heavy libs, like FFI bindings to C), it should also probably not be used like try-catch often is used in Python.

I’ve since taken a look at the ErrorT monad transformer and it seems it behaves like I expected catch to. That’s for another post though.

Mail!

Yes, I think there’s an opening for an email client, it doesn’t have to be written in Haskell of course, but if I ever get my arse into gear it will be. Especially now that mutt-ng seems to have stalled in development, and even though mutt still is being developed I’ve gotten too spoilt by using mutt-ng exclusively for the last year or so. I’ve looked extensively at sup and it’s sweet, but due to some recent changes in what kind of machines I have access to on the web it doesn’t quite fit me anymore.

What would my ideal email client look like?

  • GMail as backend, accessed through Python’s libgmail. Hopefully it won’t be too difficult to write a Haskell module to deliver this part, but using Python to begin with is absolutely acceptable.
  • Haskell for the frontend, specifically using vty for the UI.
  • Vim, Yi, or any other old terminal-based editor to write email.

I’m confident vty has enough functionality. I’ve played with libgmail enough to be confident it offers enough access to mail data to do most everything I want from a client (the missing part is sending PGP/MIME messages, but sending mail through Google’s SMTP server is a workable solution). I’ve just started looking at options for mail parsing in Haskell, identifying three and already discarding one…

Yes, it’s all vapourware at this point, but hey, I can dream, right?

N-Queens in Haskell

After reading the chapter on options, exceptions, and failure continuations from Programming in Standard ML I thought spending a few minutes on translating the code to Haskell might be fun.

I should start with a disclaimer, I’ve never coded in SML, never even read any article or book about the language or even looked at code written in it. Nevertheless I seem to have produced runnable, and presumably correct, code in a fairly short amount of time. I’ve tried to stay as close to the original code as possible, there are undoubtably better and more effective way of writing the same code in Haskell. Feel free to provide comments with improvements :-)

First the representation of the board:

data Board = Board Int Int Int [(Int, Int)]
    | NoBoard
    deriving (Show)

Then some functions to manipulate a board:

new n = Board n 1 0 []

size (Board n _ _ _) = n

complete (Board n _ k _) = k == n

positions (Board _ _ _ qs) = qs

place (Board n i k qs) j = Board n (i + 1) (k + 1) ( (i, j) : qs)

threatens (i, j) (i’, j’)
    | i == i’ = True
    | j == j’ = True
    | i + j == i’ + j’ = True
    | i - j == i’ - j’ = True
    | otherwise = False

conflicts q [] = False
conflicts q (q’:qs) = threatens q q’ || conflicts q qs

safe (Board _ i _ qs) j = not $ conflicts (i, j) qs

These are all straight-forward translations, within minimal “haskell-ifications”.

The first solution using Maybe and explicit checks for failure:

addqueenM bd =
    let try j = if j > size bd
            then Nothing
            else if safe bd j
                then case addqueenM (place bd j) of
                    Nothing -> try $ j + 1
                    Just bd' -> Just bd'
                else try $ j + 1
    in
        if complete bd
            then Just bd
            else try 1

queensM = addqueenM . new

The second uses exceptions to avoid the explicit check (note that I’ve imported Control.Exception as CE to avoid the clash with Prelude’s catch; see the documentation of catch if you don’t know why that’s necessary):

addqueenE bd =
    let try j = if j > size bd
            then error "no more space on board"
            else if safe bd j
                then CE.catch (addqueenE (place bd j)) (\ e -> try $ j + 1)
                else try $ j + 1
    in
        if complete bd
            then return bd
            else try 1

queensE n = CE.catch (addqueenE $ new n) (\ e -> return NoBoard)

The last translated version uses an explicit failure continuation to avoid both checking results and dealing with exceptions:

addqueenC bd fc =
    let try j = if j > size bd
            then fc
            else if safe bd j
                then addqueenC (place bd j) (try $ j + 1)
                else try $ j + 1
    in
        if complete bd
            then Just bd
            else try 1

queensC n = addqueenC (new n) Nothing

So far so good, but since this is Haskell, what about monads? :-) Minor changes results in the following somewhat general version of addqueenX:

addqueenH bd =
    let try j = if j > size bd
            then mzero
            else if safe bd j
                then addqueenH (place bd j) `mplus` (try $ j + 1)
                else try $ j + 1
    in
        if complete bd
            then return bd
            else try 1

With that it’s possible to lean on the type system to get something that’s similar to queenM from above:

queensHM :: Int -> Maybe Board
queensHM = addqueenH . new

It’s also easy to write a version that calculates all solutions given the size of the board:

queensHL :: Int -> [Board]
queensHL = addqueenH . new

Slightly embarrassed about continuations…

Recently I’ve spent some time trying to understand continuations better. First off I have to admit to being a bit daft because it was only recently that I realised that call-with-current-continuation (call/cc in Scheme and callCC in Haskell) actually means “call foo with the current execution point as continuation” rather than “call foo with the continuation passed to the current function”. Well, there’s no way to explain it besides daftness I guess, even though I’d like to think that my decision to look at continuations in Haskell (callCC) to learn about them (the Cont monad just might have confused me somewhat). I really should have started by looking at continuations in Scheme (call/cc). The best description I’ve come across so far is Applications of Continuations.

I still find it somewhat confusing, as can be seen in my latest use of hpaste, but it’s somewhat clearer now than before. At least I seem to be able to almost reason my way through code I write myself, but doesn’t do what I expect :-)

I’m not being alone in thinking del.icio.us is crap

Ah, someone else is feeling the pain with the del.icio.us API.

Interesting information about throttling on usage of posts/all. It all adds up to del.icio.us API being nearly useless for experimentation and interesting new uses of bookmarks. I’m just so happy there are other social bookmark sites that don’t put whimsical limitations on API usage.