(After a long hiatus of just lurking and posting to the forums, I am trying to start blogging again.)
Like many people, I recently discovered http://projecteuler.net. The site contains a set of mathematically oriented programming problems that get progressively harder. I started solving them using F#. While doing so, I've come up with some comments on how F# is really good for these kinds of problems and some improvements that would be nice and probably applicable to more general kinds of programs.
- BigInt rules! Since a lot of the problems are calculations on large integers, it is nice to have them available. It would be nice if there was a "bigint" equivalent to the "int" and "float" functions to simplify conversions. It would be really nice if there was a way to override the default numeric behavior of assuming that every number is an int; it would be nice to be able to switch to "float" or "bigint" mode and have the type checker make the appropriate assumptions.
- A minor nit, but it would be nice to have a predefined identity function. I seem to have one in each program I write (even beyond ProjectEuler).
- For most of the problems, I'd create a sequence expression with individual calculations and then aggregate the desired result after filtering. This demonstrated the convenience of sequence comprehensions, but we already knew that :-)
- I tried to avoid "normal" imperative for and while loops and created new helper functions to work on sequences: seqUntil and seqWhile would process a sequence depending on a boolean function, seqAll would see if a function was true for all values in a sequence (the counterpart to Seq.exists), seqSkip would remove the first n entries in a sequence (really creative name, there :-), etc. I think that a lot of these functions, especially the ones that are in the Haskell Prelude for lists, would be good additions to the Seq module.
- It would be nice to have some of the aggregation operations be representable in the comprehension language. This has been described Simon Peyton-Jones and Phil Wadler in Comprehensive Comprehensions for Haskell and should be applicable to F# as well.
- I've noticed that I mix the sequence comprehension syntax with the "old-style" pipeline syntax a lot, even when the function could be done in a sequence comprehension. Looking back, it seems that if I am exploring (ok, guessing) a solution incrementally, it is easier to do that by adding new Seq.map, Seq.filter, or Seq.fold functions at the end with "|>" while running each step in fsi. Would it help if there was a way to run and augment sequence comprehensions incrementally in fsi? If I knew the path to the solution(or subsolution), I would choose to use the comprehension syntax first.
- While there seems to have been an interest in having F# be an alternative to Matlab for some kinds of engineering computing, I think that it could give Mathematica a run for its money in the computational and presentation space. Adding full symbolic math support would be nice, but a harder challenge...
It has been a fun diversion to work on these problems, and interesting to see how concise the F# solutions are compared to the other languages represented. The solutions in J are always the smallest, but I haven't grokked the syntax to understand the solutions yet :-) The assembly language solutions are always interesting to read, but it is nice to see F# solutions that are as concise as the Ruby and Python solutions but running much faster...