Efficient Amortised and Real-Time Queues in Haskell
well-typed.com
well-typed.com
The Finger Tree (available in the Haskell standard library under Data.Sequence) is a really impressive data structure. It's persistent, it has O(log(min(n,len-n))) access and modification (which means O(1) cons, snoc, head, and last), and O(log(min(m,n))) concatenation.
In my testing, it was several times faster than the fastest banker's queue library I found.
So I would like to advise staying away from finger trees and other interesting data structures when lists suffice.
In case of queues they are very sufficient.
What article lacks, is the performance comparisons.
Before I just thought they were pedantic or snobbish.
It's been my observation that reading articles/posts written by Haskell programmers is a great way to be spend a fair amount of time being confused over things that you already understand, usually for this reason. In that sense, at the least, they're usually educational.
It's my suspicion that the most common path to becoming a Haskell programmer is to read too many of these sorts of things, to start using the terminology in your own writing and speech, then to find that no-one but Haskell programmers understand you anymore, leaving you no choice.
Invariants are admittedly undersold in the curricula I've seen, but the idea comes up in many places. Most people ought to have at least encountered the idea in databases, where foreign key references provide basic invariants about referencing existing rows no matter what SQL you fling at them, for instance.
Of course we’re going to talk about these ideas, because Haskell makes it easy to apply them in the real world. And if you have the choice, why would you go back to a language where you don’t have that advantage?
It's also plausible that loop or class invariants are discussed in a CS1 course to ensure that your objects don't end up in invalid states after the execution of a loop/method. But maybe the exact word "invariant" is not used as such here.
"The add operation runs in amortized constant time, that is, adding n elements requires O(n) time."
I thought memory management was hard to reason about in pure functional languages, but i never thought it could affect algorithmic complexity this badly.
Great blog with examples where something linear turns quadratic! :D
Most of the examples show that being this high at the abstraction level disallows you to properly evaluate the complexity of the code you are writing. Something that might look simple and linear can in fact have a quadratic behavior.