Sententia cdsmithus

June 28, 2007

The Two Meanings of Declarative

Filed under: Uncategorized — cdsmith @ 10:21 pm

For about the seventh time, now, I’ve been “corrected” on something in a way that isn’t really correct.  The issue here is what is meant by a declarative language.  Haskell and SQL are both called declarative.  There are, though, very different senses in which these languages might qualify as declarative.

Haskell is a declarative language in that the program can be treated as a statement of facts, rather than as a set of commands that are sequenced in time.  These facts, though, are about all sorts of things.  They express the structure of the problem, but also the algorithms used to solve the problem, the intermediate data structures used between steps, and so on.  I can implement merge sort, quick sort, and bubble sort in Haskell; and I can tell the difference.

SQL is a declarative language in that it’s a formal way for me to say what I want.  The database decides how to find it.  It’s true that there are some limitations: some databases perform far better with joins than with correlated IN clauses, for example.  By and large, though, these are warts.  I can’t describe most algorithms in SQL.  It would be meaningless to try to identify whether an ORDER BY clause does a merge sort or bubble sort.  The basic algorithms used by the system can depend on the definition of the table, the existence of indices, and even statistics gathered by the DBMS over time.  You can bet your bottom dollar those algorithms aren’t themselves written in SQL (or even in PL/SQL or some other procedural extension).

These are, in other words, two different definitions of “declarative.”  One language allows you to declare things about the computation.  The other restricts you to declaring things about the problem.  Critics and armchair observers would be well-advised to determine which is meant before blurting out “that doesn’t make sense, because Haskell is a declarative language.”

</rant>

June 26, 2007

What To Know Before Debating About Type Systems

Filed under: Uncategorized — cdsmith @ 9:09 pm

I started writing this as a blog entry, but it reached 15 pages.  So it moved to a place of its own.

http://cdsmith.twu.net/types.html

I’ve tried to be reasonably fair.  Enjoy!

June 25, 2007

Blogging in Haskell

Filed under: Haskell — cdsmith @ 8:12 pm

Yesterday, I finally decided to figure out syntax highlighting for Haskell in my blog.  I ended up finding two different ways to do it, so I’ll describe both of them, along with links to the (small bits of) code that I ended up writing in the process to help out.

Attempt 1: The Star-Light Approach

The first approach is to use Dean Edwards’ star-light JavaScript/CSS library.  This is a nice piece of client-side JavaScript and CSS that syntax highlights your source code for you, in a variety of languages.  All you have to do is enclose it in a tag like <pre class="javascript"> or <pre class="php">.  The CSS file (which you also need to reference from your page) takes care of invoking some JavaScript code that scours your page and does the syntax highlighting on the client.

Unfortunately, Dean Edward’s code doesn’t do Haskell by default.  So I wrote the code to do it, and you can download a modified version of star-light here.  It wasn’t terribly difficult, but neither is my code very elegant.  It mostly works, though.  Limitations that I know about are listed in the comments at the beginning of star-hs.js, and include poor handling of nested comments, “gaps” in string literals, and non-ASCII characters, and some overly excessive highlighting of Prelude symbols and the pseudo-keywords as, qualified, and hiding when they should be left alone.

Star-Light: Advantages

  1. Very little effort on your part.
  2. Support for several different languages.
  3. Client-side programming is all the rage!

Star-Light Disadvantages

  1. Uses non-standard CSS extensions, so limited portability.
  2. You have to trust my code. :)
  3. The parser is based on regular expressions, so it’s ultimately hopeless for Haskell.

In the end, though, neither of these is the reason that I didn’t end up using star-light for syntax highlighting.  I didn’t use it because the blogging host I’m using, WordPress, strips any “dangerous” stuff out of CSS and bans JavaScript from their blogs.  They claim it’s a security risk for them.  I’m a little worried, and you should be too, that a very popular blog platform believes that their security validly depends on client-side behavior.  I’d be even more worried if I thought they might be right.  Ah well; given the chance to choose again, I’d have avoided WordPress for a blog, but it’s a little late for that now.

Off to my second attempt…

Attempt 2: HsColour + Plugin

Having given up on client-side syntax highlighting, I turned to the obvious choice for server-side implementation: HsColour.  This nifty little project specializes in syntax highlighting Haskell, and can output HTML.  If only it were a little easier to use when writing a blog entry…

I write my blog entries using Windows Live Writer.  While I’m not at all addicted to it, it’s a nice alternative to the web-based editors in conventional blogs, and it doesn’t have the tendency to freeze up randomly that characterizes WordPress’s built-in editor.  (Did I mention that I’d never start a blog with WordPress again?  I thought so.)  It also has a plug-in interface, so I built a simple plug-in that asks for a block of code, runs it through HsColour, and sticks the result into a <pre> block in the blog.  Wanting to do the same for inline code fragments, I added a second plugin to ask for a line of code and put it into HTML <code> tags.

The plugin can be found here as a DLL file, which you can just drop into the plugins directory underneath Windows Live Writer’s installation directory to install it.  You’ll need HsColour installed and in your path.  If you want the source code, look here.  This plugin calls HsColour with the CSS option, so you’ll need to add a CSS stylesheet to define your syntax highlighting styles.  Alternatively, you could edit the plugin to use -html instead.  (WordPress, for example, charges extra for writing a CSS file even with their “security” limitations; did I mention I’d never start another blog with them?)  If you choose CSS, you’ll need styles for the selectors .keyword, .keyglyph, .layout, .comment, .conid, .varid, .conop, .varop, .str, .chr, and .num. The only confusing one is .layout, which I initially assumed had something to do with omitting squiggly braces. It turns out it’s just more reserved symbols and should probably be set to the same thing as .keyglyph.

HsColour + Plugin: Advantages

  1. Result works on all browsers with basic CSS support.
  2. The planet.haskell.org server has (boring) HsColour CSS entries, so it works there!
  3. HsColour is probably better at correctly parsing the language.

HsColour + Plugin: Disadvantages

  1. Only Haskell works; other techniques needed for other languages.
  2. My plugin only works on this one piece of blog writing software.

Attempt 2.5: Another Loose End

Another annoying thing about WordPress is that their blog software converts normal old everyday quote characters to “smart quotes”.  This is merely annoying for regular text, but it’s absolutely fatal for source code.  (Did I mention I’d never start another blog with WordPress?)  One more quick change produces a half-fix for this.  You should only need this if you are using WordPress as well.  The idea is to hide quotes from the WordPress code-mangler by writing unnecessary HTML entities.  Adding the appropriate HTML escape codes (which WordPress won’t let me write, but are an ampersand, followed by #, followed by either 39 or 34, followed by a semicolon) at line 79 of HsColour’s HTML.hs does the trick.

This sort of fixes the problem.  Unfortunately, Windows Live Writer helpfully notices that these entity tags are not needed, and converts them back to spaces for me every once in a while.  For the time being, my strategy for solving this is to be vigilant.  If you notice a problem with smart quotes in source code in my blog, just say so and I’ll try to fix it.

That’s all I’ve got.  Hope it was helpful.

June 24, 2007

Learning Haskell and Number Theory: GCD and Higher Order Functions

Filed under: Haskell, math — cdsmith @ 9:24 pm

This is the fourth installment of my series “Learning Haskell and Number Theory”, in which I work through Gareth and Mary Jones’ text book, Elementary Number Theory, and translate its ideas and algorithms into Haskell.  In the last installment, I wrote a function to compute the greatest common divisor of two numbers.  In this installment, we will play with higher order functions, and culminate with the extension of greatest common divisors to an arbitrary number of inputs.

The second of the two GCD implementations in the previous installment looked like this:

gcd2 0 0 = undefined
gcd2 a b = let next (x,y)    = (y, x `rem` y)
               vals          = iterate next (abs a, abs b)
               Just (ans, _) = find ((== 0) . snd) vals
           in  ans

The expression iterate next (abs a, abs b) is interesting, in that its first parameter (next) is itself a function. This general idea can be extended to all sorts of tasks, and is one of the cornerstones of functional programming.  It goes by a name: higher order functions.  (The general intuition here is that a first order function is one that operates on basic pieces of data, such as integers or strings; a second order function is one that operates on first order functions, and so on.  I don’t like this intuition because it ignores the fact that what’s chosen as “simple” data in any given language is arbitrary; but I don’t get to pick these names.)  A higher order function can take other function as parameters, and it can evaluate to a function as its result.  If it does both of these, it can be seen as a sort of transformer of functions.

I intend to write a higher-order function, and then talk about some of them that are provided in the Haskell Prelude.  Before I can get there, though, I need to clean up something that many of you pointed to in comments earlier, and that’s the meaning of the greatest common divisor of zero and zero.  The Jones text calls it undefined, which makes very literal sense.  Everything divides zero, and the set of integers has no greatest element.  Therefore, there can be no greatest divisor of zero.  However, as many of you pointed out, defining gcd(0, 0) = 0 has some nice benefits.

One of those benefits is that it allows me to continue where I want to go.  (I’m still following the book, but in fact the book is wrong here.  As an exercise, if you’ve got the book, see if you can find the error in the book’s answer to exercise 1.9.  There must be an error, but the statement for which it wants a proof is not true!)

Therefore, we’ve got:

gcd1 :: forall a. Integral a => a -> a -> a
gcd1 a b = gcd1' (abs a) (abs b)
    where gcd1' a 0 = a
          gcd1' a b = gcd1' b (a `rem` b)

Suppose we want the greatest common divisor of more than two numbers.  Following example 1.9 of the Jones text, we could define:

gcd' :: forall a. Integral a => a -> a -> a -> a
gcd' a b c = gcd (gcd a b) c

gcd'' :: forall a. Integral a => a -> a -> a -> a -> a
gcd'' a b c d = gcd (gcd (gcd a b) c) d

gcd''' :: forall a. Integral a => a -> a -> a -> a -> a -> a
gcd''' a b c d e = gcd (gcd (gcd (gcd a b) c) d) e

Oops… looks like we’re going on forever here. We could define gcd'''' or even worse.  Better is to exploit this fact:

*NumTheory> :qc \a -> gcd1 0 a == abs a
+++ OK, passed 100 tests.

Great!  So that gives us a starting point, 0, into which we can add numbers one by one until we have the greatest common divisor of them all.  We need a function that converts a list of integral values into a single integral value representing the GCD.

gcdmany :: forall a. Integral a => [a] -> a
gcdmany [] = 0
gcdmany xs = let x = init xs
                 y = last xs
             in  gcd1 (gcdmany x) y

The new functions init and last do what they say. The init function returns the initial part of a list — more precisely, all but the last element. The last function returns the last element of the list. Note that x is again a list!  There is, of course, one more thing that may be tricky about this code: it is recursive, like most useful things in Haskell.  Some careful thought, though, should convince you that this does exactly what the book suggests: from left to right, it applies the greatest common divisor algorithm to each pair of numbers until it gets to the end.

It’s quite inefficient, though.  At turns out that in haskell, it’s much faster to pick the first element from a list than the last one, because lists are singly linked in the forward dimension.  A more complicated, but faster, implementation is:

gcdmany :: forall a. Integral a => [a] -> a
gcdmany xs = gcdmany' 0 xs
    where gcdmany' p []     = p
          gcdmany' p (x:xs) = gcdmany' (gcd1 p x) xs

If you’ve got the hang of Haskell, you can check that this works.  The only thing I haven’t mentioned yet is the list constructor, :, which is basically LISP’s cons function if you know other functional languages.  If the code remains a mystery to you (which would be normal if you’re new to the language) you can study it, or just trust me.  The problem is that this is a little more complicated than we’d like to write again and again, and it turns out that you want to do exactly this lots and lots in Haskell code!  A higher order function would be handy, and the standard library provides one, called foldl, that does exactly what we’re looking for.

gcdmany :: forall a. Integral a => [a] -> a
gcdmany xs = foldl gcd1 0 xs

The last thing we can do, just be fancy, is called eta reduction.  This is the observation that if f(x) = g(x) for all x, then f = g.  This property is sometimes known as extensional equivalence, and it’s a property of pure functions, by definition. The xs at the end of the left and right-hand sides of the Haskell equation match up just like the xs in the math equation, and we can remove them.

gcdmany :: forall a. Integral a => [a] -> a
gcdmany = foldl gcd1 0

And that’s pretty simple.

June 22, 2007

Remaining Questions about HAppS

Filed under: Haskell — cdsmith @ 3:40 pm

This is a list of questions I need answered about HAppS’ MACID monad before I can decide to use it for a large-scale application.  It’s a long list, but I don’t mean to imply that the answers are bad; indeed, I’m hopeful they will turn out okay.  I’m making the list in the hopes someone can point me in the right directions, as just reading the source code is slow going so far!

  1. Is it feasible (even by extending the HAppS framework, if needed) to load balance a HAppS application across multiple servers?  I’ve got performance problems already with the old version of this application; I’m hopeful that many of them can be solved by dropping this Java object-relational mapper - which generates SQL that I never see - with Haskell code for which I can use smart data structures and algorithms and fix the problems.  Still, the hope is that more people use this in the future, and I’d hate to permanently give up the option of clustering or load balancing.  Although it wouldn’t be immediately needed, it remains worthwhile to have the choice.
  2. Is it feasible (even by extending the HAppS framework, if needed) to have HAppS store only part of its data at a time in memory?  While servers are getting more and more powerful over time, applications are using more and more data as well.  The data backup files for the application I’ve currently porting to Haskell are 9 GB in size, after compression.  I’m hoping that this increases over time.  While most of this data could potentially be moved into auxiliary files outside of the HAppS MACID monad, it’s still a little questionable whether I’d want to limit the data to the size of the server’s RAM.  The web site says that everything has to fit in RAM; but I don’t know if that’s because of something fundamental about the way the system works, or just because that’s what is implemented today.  The talk of moving to S3 and EC2 seems to indicate the latter (more promising) state of affairs.
  3. Is it feasible (even by extending the HAppS framework, if needed) to tie HAppS’ MACID transactions to transactions in external information systems via a two-phase commit protocol?  One of the key goals of the software I’m developing is integrating with other systems seamlessly, and that likely means allowing changes to HAppS-controlled data to participate in a distributed transaction.
  4. When I change the data structures for a HAppS application, it fails to load with the old state.  Is there an easy technique for migrating data when one needs to change the data tracked by the application?
  5. What is the best way to manage (i.e., interactively query and update) live data from a HAppS application outside of the pre-planned application functions?  For example, if I’m asked by my boss how many people with a first name of Tiffany have used the application after midnight since 17 days ago, I can currently throw together some SQL and find out.  Now, can I throw together some Haskell and find out?  How would I do that?  The only thing that comes to mind is something like lambdabot, which uses hs-plugins to compile and then dynamically load some code and run it.  I can do this, but it’s a little odd and it seems like there’s be an easy answer to this.

June 21, 2007

A Hack for Approaching Haskell Libraries

Filed under: Haskell — cdsmith @ 10:55 am

One of the most difficult problems I find in learning new libraries and modules is where to start.  If you start in the obvious places, there are inevitably zillions of abstractions that just don’t make sense yet.  As a quick kludge, I write the following Haskell code; it examines a set of modules in a directory, and sorts them by the number of dependencies on other modules.  The result is that if module A depends on module B, then B will be listed before A in the result (except for circular dependencies).  If you read the source code in the order given here, there’s more chance of understanding it all.

So here’s the code to build such a list:

import System
import System.Directory
import IO
import Data.List
import Data.Char
import Data.Maybe
import Data.Ord

{-
    Read a Haskell *.hs file and get a list of all the modules
    that it imports.
-}
findDeps base pkg = do
        let hi = base ++ (map dotToSlash pkg) ++ ".hs"
        ex <- doesFileExist hi
        if not ex then return [] else do
            src <- readFile hi
            let imps = filter isImport (lines src)
            return $ catMaybes $ map getTargetModule imps

    where dotToSlash '.' = '/'
          dotToSlash x   = x

          isImport (' ':t)  = isImport t
          isImport ('\\t':t) = isImport t
          isImport t        = "import" `isPrefixOf` t

          getTargetModule s = let pre = takeWhile (/= '(') s in
                              find (isUpper . head) (words pre)

{-
    Find the transitive, reflexive closure of the relation defined
    by the findDeps function.  This returns a list of ALL modules
    that this one uses or depends on, directly or indirectly.
-}
allDeps base mod = allDeps' [mod] [mod] where
    allDeps' (m:ms) full = do d <- findDeps base m
                              let d' = filter (not . flip elem full) d
                              t <- allDeps' (d' ++ ms) (d' ++ full)
                              return (m : t)
    allDeps' [] _        = return []

{-
    Usage: OrderByComplexity  

        = directory where source code is found.  This MUST
                end in '/'
     = file that lists the modules you're interested in,
                one per line.  This is often taken from a .cabal
-}
main = do [ base, pkgFile ] <- getArgs
          pkgStr            <- readFile pkgFile
          let pkgs           = lines pkgStr
          mods              <- mapM (allDeps base) pkgs
          let deps           = zip pkgs mods
          let deps'          = sortBy (comparing fst) deps
          mapM_ print $ map fst $ sortBy (comparing $ length . snd) deps'

June 19, 2007

Are RESTful Web Services Like Functional Programming?

Filed under: Uncategorized — cdsmith @ 6:57 pm

This comment by bew caught my attention on a recent post of mine.

It’s a bit funny that someone interested in Haskell is that negative about REST. With REST, GET and PUT are like pure functions. You will always get the same result, irrespective of how often you call them with the same parameters.

It’s interesting to me, not so much as a statement about REST, but as a statement about ways of understanding functional programming.  Ultimately, it boils down to why functional programming languages are a good idea in the first place.  So here’s a quiz.

Question: Why are functional programming languages a good idea?  (Select all that apply.)

  1. Because one can safely do the same thing over and over again.
  2. Mutation belongs in comic books, and has no place in programming.
  3. They provide powerful tools for building abstractions.
  4. They provide powerful tools for analysis of programs.

My answers: 3 and 4 only.  I really don’t fundamentally care about answers 1 and 2.  The definition of referential transparency and the lack of mutation are by all means obvious and visible aspects of functional programming, but the importance of functional programming is not tied to any desirability, in and of itself, of idempotence or lack of mutation.  Functional programming is worth anyone’s attention only because it occupies a nice space in which powerful abstraction and powerful analysis, two goals that are often in strong tension, are both near at hand at the same time.  That, rather than anything else, is why they are important and successful.

As bew says, some REST methods are idempotent, and mutation is clearly marked.  Unfortunately, the more interesting bits are missing.  Indeed, there is active resistance in the “REST is cool” groups toward building any further abstractions at all on top of REST, and I see only limited support for an argument that transforming, manipulating, or analyzing REST services is particularly powerful either.  REST isn’t alone in sharing some characteristics with functional languages (to the extent that it does, which is a stretch) but missing the benefit.  It’s not even the best example.  XSLT is way more purely functional in nature, and at least as fundamentally uninteresting to boot, as RESTful web services.

So my answer to the subject line: Are RESTful web services like functional programming?  No, at least in any interesting way.

Does any of this mean I’m beelining toward SOAP?  No; after all, no one could say with a straight face that SOAP provides powerful tools for abstraction or analysis either.  RESTful web services may be a good idea for purely pragmatic reasons — poor quality of implementation of SOAP, ambiguous specifications, etc.  That isn’t the popular claim though.  The popular claim is that REST is some kind of ideal; a set of principles that should be applied to any communication delivered over HTTP.  I still say hogwash.

June 18, 2007

Is TIOBE Fatally Flawed?

Filed under: Haskell, Uncategorized — cdsmith @ 7:38 pm

update: As Bogdy mentions in the comments, my reasoning here was based on false assumptions. It still seems clear that ranking APL above Haskell, along with other anomalies, disqualifies TIOBE for any serious purpose, at least past the top ten or so languages. My rankings should be ignored, though.

During a debate at work about using Haskell for a project, a coworker pointed out that Haskell is ranked #41 on the TIOBE.  On further investigation, things look really fishy.  Common interpretations of TIOBE include the amount of “community”, “buzz”, or “excitement” around a language.  By none of these standards can APL reasonably edge out Haskell.  I dug further.

Summary of findings: the TIOBE is severely broken.  It is falling victim to the fact that search engines grossly overestimate their number of results.  For example, if I search Google for “haskell programming”, as TIOBE does, the resulting page proudly estimates 44,500 results.  However, if I click through the results, I hit the end of the list after only 652.  Nice for marketing Google, perhaps, but it seems the estimate was rather poor.  Similar things happen with other languages.

TIOBE, despite using several search engines, seems to correlate well with Googles estimated (i.e., phony) number of results.  It correlates very badly with the actual number of results.  Here’s my corrected TIOBE list, built only from the top 50 languages in the original list.  In order to comply with Google’s terms of service, I painstakingly did this by hand; so I didn’t go any further.

There are some things that are initially surprising; but some thought indicates they may be reasonably expected.  Languages near the top tend to be those that are somewhat old (more time to write about them) or commonly used - past or present - in business and/or the academic world.  That’s because these languages have a reason to have a lot of web pages written about them.  One example: Prolog clearly isn’t a commonly used language nor one with a lot of community, but it’s taught by just about every computer science department in the world’s “programming languages” intro courses, because they feel better including something besides imperative and functional languages.  Hence, it’s been written about a lot.  One can see the effect of the “big community” effect though, if only in languages that appear above where you’d expect to see them.

I also split Lisp/Scheme into Lisp and Scheme separately, and dropped Natural because Googling for “natural programming” turned up more irrelevant results than relevant ones.

Without further delay, the “Chris” update to the TIOBE list.

  1. Fortran
  2. COBOL
  3. C
  4. Logo
  5. JavaScript
  6. MATLAB
  7. Prolog
  8. RPG
  9. ML
  10. Pascal
  11. Lingo
  12. Scheme
  13. LISP
  14. REXX
  15. C++
  16. Forth
  17. Smalltalk
  18. Icon
  19. SAS
  20. ABAP
  21. Tcl
  22. IDL
  23. FoxPro
  24. Haskell
  25. Bash
  26. Java
  27. CL
  28. APL
  29. ColdFusion
  30. Delphi
  31. Perl
  32. BASIC
  33. Objective C
  34. Erlang
  35. Lua
  36. Ada
  37. Awk
  38. ActionScript
  39. VBScript
  40. Ocaml
  41. D
  42. Dylan
  43. C#
  44. Python
  45. Ruby
  46. Transact-SQL
  47. PHP
  48. LabView
  49. S-lang
  50. PL/SQL

June 17, 2007

REST Web Services and Superstition

Filed under: Uncategorized — cdsmith @ 7:47 pm

It’s been forever since I write anything.  My plans for writing haven’t changed; I’ve just been swamped at work, sick, and a few other things all at once.

For now, let’s play a game called “tell me why I’m wrong.”  My argument: RESTful web services are often hyped, and only occasionally beneficial.

I do admire this: the “REST web services” marketing has been phenomenal.  Wow!  This is one of the great success stories of rhetoric.  Web services meant something in the very early days.  By proclaiming loudly and often that SOAP and REST are alternative types of web services, it was possible to get acknowledgement of REST every single time someone talks about web services, at the risk of being “corrected.”  Never mind that the whole “the web itself is a REST service” nonsense belies that the term has now been stripped of any meaning; millions of people will assume someone’s stupid if that person doesn’t play along with taking “REST web services” seriously.  It’s a nice play on the human dislike for being thought wrong.

Now, the reasons to prefer non-REST web services (i.e., the original kind, for which the phrase was invented) are clear.  Basically, it comes down to this: average programmers don’t have have to do anything.  Marshalling, networking, and everything is handled in a library that exposes an interface - on both sides of the connection - exactly analogous to the set of things someone will actually want to do.

Now, it seems, I should make my web services more RESTful.  There really seems to be only one reason, and it amounts to setting up “the web” as an ideal to strive for, and then pointing out that SOAP-based services don’t meet that ideal.  Of course they don’t; that was never the right goal to begin with.  If I’m writing software for foo, I ought to be concerned with whether my remote interface is consistent with the goals and ideals of foo, rather than the web.  When providing any kind of remote interface to some piece of functionality, the goal should be to accurately represent that functionality.  No one cares about the transport protocol.

Perhaps we could build techniques for abstraction that make REST web services as easy as SOAP.  Great idea, and WADL tries to do it.  But oops, Joe Gregorio says that’s not good.  Of course, Joe is not alone.  It seems he’s part of a massive movement of people scrambling to block this approach.  The technique is similar: it’s not “RESTful” enough; in other words, too little like the web.  Apparently, abstraction is not web-like enough, so we should drop it.

Yes, “the web” has been successful.  It’s been successful because it fulfilled a need, and made choices that were the right ones for its problems and challenges.  When faced with different challenges, other decisions are the right ones.  Leonard Richardson (author of the popular book RESTful web services) admits in an interview with InfoQ that many more dynamic web applications (those that solve problems different from the web) don’t follow REST principles at all.  Of course, he follows that with a comment that the web would just be better if they did; but with no justification.  These are people who solved different problems, and they used different ideas to do it.

So I view REST as a superstition; the web is great, and it does these things, so we should to.  Jedediah died, and he walked under a ladder, so we shouldn’t walk under ladders.  Is it all the same glitch in the human psyche?

June 6, 2007

Learning Number Theory and Haskell: Greatest Common Divisor

Filed under: Haskell, math — cdsmith @ 3:12 pm

This is part three of my series, “Learning Number Theory and Haskell”, in which I work through Gareth and Mary Jones’ Elementary Number Theory and translate the ideas and concepts into Haskell. In the previous two parts, I used QuickCheck to verify some theorems and translate some ideas into Haskell code.

It is widely speculated that the first real algorithm worthy of the name was due to Euclid, when he described how to calculate the greatest common divisor of two terms. What better place to start, then in writing a first serious algorithm in Haskell? (Besides, the textbook does this next.) In the process, I’ll use “equational reasoning” (a popular word in functional programming) to improve the code. Then I’ll try something completely different to finish off

First, let’s write a type signature. Greatest common divisors can be calculated with integral values only, and maps two numbers to a result. The signature is:

gcd1 :: forall a. Integral a => a -> a -> a

For a first version of the algorithm, I plan to transcribe the proof from the text as code. There are a few trivial cases involving zero gotten near the top of page 6. We can write those separately using pattern matching.

gcd1 0 0 = undefined
gcd1 a 0 = abs a
gcd1 0 b = abs b

There are a few more special cases for non-zero arguments.

gcd1 a b | a <  0    = gcd1 (-a) b
         | b <  0    = gcd1 a (-b)
         | a == b    = a
         | a <  b    = gcd1 b a
                                 -- Phew!
         | otherwise = gcd1 b (a `rem` b)

Let’s test against the built-in gcd function from the prelude. The only subtlety here is that since gcd 0 0 is undefined, we should avoid calling it.

*NumTheory> :qc \a b -> (a /= 0 || b /= 0) ==> gcd1 a b == gcd a b
+++ OK, passed 100 tests.

We’ve got a working gcd1. However, it is terribly unsatisfying. By following the textbook to the letter, we ended up with a function defined with eight separate cases. Yuck!

The problem is that our number theory textbook handled a lot of stuff as special cases to get it out of the way easily for the proof. Many of those special cases aren’t all that special after all, and we can clean this up by finding equivalent cases and combining them. This is really easy to do and get right in Haskell, once you’ve got the hang of it, because Haskell functions can be read and substituted just like algebra equations. This concept is often called “equational reasoning”, and is cited as an advantage of pure functional programming. The ease of doing this is a direct consequence of not having side effects.

The last two cases cover when a < b, and a > b, respectively. However, the last case subsumes the next to last one, because if a < b (with a and b both positive), then a `rem` b is equivalent to a. That eliminates one case. Similarly, the third from last case is unnecessary. If a = b, then gcd1 a (a `rem` b) evaluates to gcd1 a 0, which in turn evaluates to abs a. Since we know a > 0 if the evaluation gets this far, this is the same as a. This case is also unnecessary. A similar argument proves that gcd1 0 b = b is unnecessary. That leaves:

gcd1 0 0 = undefined
gcd1 a 0 = abs a
gcd1 a b | a <  0    = gcd1 (-a) b
         | b <  0    = gcd1 a (-b)
         | otherwise = gcd1 b (a `rem` b)

This is better, but it’s even shorter to promote the check for negative values of a and b and for gcd1 0 0 to an outer function. The where keyword can be used to define an inner function that is available only within a particular top-level function. The result looks like this:

gcd1 0 0 = undefined
gcd1 a b = gcd1' (abs a) (abs b)
    where gcd1' a 0 = a
          gcd1' a b = gcd1' b (a `rem` b)

Eliminating all of these special cases could be interpreted as an indication that we didn’t need them to begin with.  As an exercise, try rewriting the proof in the text without assuming anything except that a and b are non-negative and are not both zero.

Rerunning the test suite to verify:

*NumTheory> :qc \a b -> (a /= 0 || b /= 0) ==> gcd1 a b == gcd a b
+++ OK, passed 100 tests.

Another implementation of the greatest common divisor is interesting (though, ultimately, it doesn’t perform as well.) One way to look at the algorithm is that we are inductively defining a list of number pairs which all have the same divisors. We start with (|a|, |b|) as the first element in the list, and then define a function to get from there to the next element. That looks like this:

gcd2 0 0 = undefined
gcd2 a b = let next (x,y)    = (y, x `rem` y)
               vals          = iterate next (abs a, abs b)
               Just (ans, _) = find ((== 0) . snd) vals
           in  ans

We first define a next function that takes us from one pair of numbers to the next. Then we use a Haskell standard library function, iterate, to build a list of values resulting from successive applications of next to the pair of numbers. Finally, we look for the first entry from that list that has 0 for its second number. The result is the first number of that pair. You can use QuickCheck to verify that it gives the same answer as the other two algorithms above.

This introduces an explicit data structure to represent the structure of the algorithm. Sometimes, doing this can make algorithms clearer. In this case, it’s just an interesting alternative. It involves some new concepts: an infinitely long list, a higher-order function, and another interesting use of pattern matching. If you don’t understand it yet, take some time to poke around the standard library documentation. Don’t despair, though; I’ll talk about more of these ideas in future installments.

Blog at WordPress.com.