Profiling output claims 0.20 seconds runtime (still; the difference is a few "ticks" that aren't noticeable in the calculated time). It's a little better, but we are definitely in the realm of diminishing returns. Let's check out the cost centers:

Before, we had digitsIn and digitsIn.digitsIn', which collectively consumed 12.5% of the time and 9.3% of allocation. Now we have bDigits.bDigits' and bDigits.bDigits'.upToN, which just eat 8.7% of time and 4.9% of allocation (though speaking of allocation, of course we now have those three new lists sitting around).

UPDATE: It bugged me that I was grabbing a whole prefix of a list when I really only wanted the last item of that prefix (along with something like its length), so I added yet another helper function, resulting in

where twoToThe is just like tenToThe, using powersOfTwo instead of powersOfTen.

That helped; with the change, the cost center listing shows bDigits, bDigits.bDigits', and lastLE.lastLE' collectively chowing down on just 3.3% of total time and 2.1% of allocation, which beats the heck out of 8.7 and 4.9. The -hc heap graph shows the peak at around 6.5 MB rather than the 8 it sailed up to when we went to the semilattice trees.

Popular posts from this blog

Therefore, I will follow the excellent advice of Stephen Diehl, and will not write a monad-analogy tutorial. Instead, I will say: do the 20 Intermediate Exercises, and take the Monad Challenges. To paraphrase Euclid, there is no royal road to Monads; the exercises and challenges take you down that road at whose end you'll see at least part of why Monads are so useful.

If you were trying to learn group theory and people were standing around you saying "groups are like the integers", "groups are like Rubik's Cube", "groups are like m x n matrices", "groups are like baryons and mesons", your situation would be much like the student of Haskell amidst all the monad analogy tutorials. In a sense they're backwards. All those things are groups, just as burritos et al. can at least be thought…

I came across the excellent Monad Challenges, a collection of exercises designed to take you through what have become some of the standard example monads and take you through the process that motivates monads as a way to handle these seemingly diverse data structures. Both the Monad Challenges and the 20 Intermediate Exercises are well worth your time. Doing them both is helping me a lot.

That said, they don't quite match up. 20IE's banana is flip bind and apple is flip ap. (This isn't unique; the also excellent Learning Haskell from first principles has as an exercise writing bind in terms of fmap and join, but the declaration it gives has the type of flip bind. The authors do point this out.) As a result, I find myself with something that there's got to be some way to simplify, of the form

foo = flip $ (flip mumble) . (flip frotz)

I'd like to think there's some sort of distributive-like law to be found and used here... watch this space.

fivethirtyeight.com has a weekly column, "The Riddler". The Riddler poses two problems in each column. The first, "Riddler Express", is intended to be an easier problem that one can solve quickly, while the second, "Riddler Classic", is more difficult. Modulo vacations, it appears each Friday, and if you submit a solution by the end of the following Sunday (Eastern Time) , you will be among those who might be given credit for the solution in the next column.

The August 28th column's Classic problem is as follows: what's the longest sequence of integers x[i] for 1 ≤ i ≤ n such thatfor all i, 1 ≤ x[i] ≤ 100for all i < n, either x[i+1] is a multiple of x[i] or x[i+1] is a factor of x[i]for all i, j, x[i] = x[j] iff i = j, i.e. the x[i] are all distinct
(The last constraint avoids trivial sequences like 2, 4, 2, 4, 2, 4... which can go on forever if repeats are permitted.)

One way to characterize this problem is to look at it as a graph with a hu…