Cute Haskell Code
For some recent supervision work on my Security lectures, I was given the task of decoding a string encrypted with a simple shift cipher. This cipher, given a key, simply moves each letter on in the alphabet by an amount given by the key, wrapping at the end. Being a good functional programmer, I decided to implement a brute force solver for this in Haskell, and I’m rather pleased by the terseness of the result, so I felt compelled to share it.
If you ignore the boilerplate, there’s only two lines of actual code there :-). I happen to think it’s rather understandable, though I’d be interested to get the opinion of someone who isn’t a Haskell hacker on the veracity of that statement. A hint you may need understanding it is that cycle a_list
just returns the list which is a_list
concatenated infinite times, and that !!
is Haskells list indexing operator.
On this note, I saw an interesting blog post at retrospections the other day which compared the LOC count for a number of open source source control programs: Darcs (Haskell) and Mercurial (Python) were tied at 20KLOC, with the next best being Bazaar-NG (Python) at 47KLOC. Obviously this isn’t a strictly apples-to-apples comparison, though, so take it with a grain of salt!
Mmm, that's a nice solution too. Though what I particularly liked about the ['A'..'Z'] style is that it never at any point did the ASCII conversion: it was just a literal encoding of how a human would think about the problem.
Maybe more readable?
> import Char
> shift i x = chr $ constrain $ ord x + i
> where constrain n =
> let a = ord 'A' in
> (n - a) `mod` 26 + a
Maybe not...
I had to add a $ after error to get your program to compile. Now, here's my attempt at being cute:
shift i x = (dropWhile (/=x) $ ['A'..'Z']++['A'..'Z']) !! i
This gives the error "index too large" from (!!) when x is not in ['A'..'Z'] or i is not in the proper range. (You'd want to check the arguments more carefully in a real program.)
Ah, that's very nice indeed :-). And yeah, about the compile error: mea culpa. In my code that was "undefined", but I felt I should add some error handling to clean it up for the post :-).