sequences

Wolfgang Thaller wolfgang.thaller at gmx.net
Fri Apr 9 16:04:16 EDT 2004


Ross Paterson wrote:

> To have something concrete to discuss, I've placed a structure based on
> Edison at
> docs: http://www.soi.city.ac.uk/~ross/seq/
> code: http://www.soi.city.ac.uk/~ross/seq.tar.gz

Looks nice. It's nice and simple, and I could start using it quickly, 
without breaking too much of my code.
Some naming nitpicks:
* reduce1 and reducel are nice names, but they look almost 
indistinguishable in some fonts. Luckily, I don't use such a font for 
programming, but my browser does for displaying the docs.
* indexM: I feel that 'M' stands for 'Monad', not 'Maybe'. What about 
'Mb' instead?

The main difference to Robert's approach, aside from his anti-list 
propaganda ;-), seems to be that it uses a Haskell98-compatible 
single-parameter type class.
This means that concrete Sequence instances can't add an Ord context 
later - Are we sure that there are no useful implementations of the 
Sequence class that require their members to be instances of Ord? I 
definitely can't think of any, but perhaps someone else can?
Also, we might really want to add an abstract collection framework 
later; that will have to use MPTCs, and we will probably want Sequence 
to be a subclass of that. Also, sooner or later we will move empty and 
isEmpty to the general Collection class, won't we?
Are there many people who will want to use the new framework but stay 
with plain Haskell98?

Robert Will wrote:

> So here is a short argument in favour of my choices:
>
> 1. The class "OperationalSequence" in the Abstract Collections is an 
> MPTC
> that makes no restrictions on the element type.  I dubbed it
> "Operational", because without an equality over Sequences we can't give
> executable algebraic specifications.

Hmmm... so why should that fact be recorded in the name? Let's keep the 
names simple. I'd rather rename your 'Collection' class to something 
like CollectionEq, because

> 2. Also the names are choosen not to be compatible with the past, but 
> to
> be combatible with the future: the names of the Sequence operations fit
> well with those of all other Collections.  Many names are shared and 
> have
> the same semantics on all Collections.

Who says the future _shouldn't_ be compatible with the past? This is 
one reason why I wouldn't want your libraries as they are now to be 
"the future"; With Ross's proposal, I can start using it in the few 
places in my programs where lists are not appropriate, without breaking 
much of the rest. To use Dessy, I'd either have to change a lot of my 
program, or I'd have to import it qualified :-(.

Another problem I have with the names are those names_with_underscores. 
All the Haskell libraries, and all other Haskell code I've worked with, 
has always used namesWithoutUnderscores. If you want to replace part of 
the Prelude with something that used names_with_underscores, prepare 
for a religious war ;-).

> The absurdness of the "list-compatible" approach shows in the 
> ridiculous
> default running times for 'cons' O(1) and 'snoc' O(n), really what's 
> the
> big difference between those operations?

Absurdness? Ridiculous? Your language is very strong. Or should I say 
It's ridiculously strong and you are absurdly sure of your own opinion 
;-) ? (Sorry, couldn't resist to use the same language on you...).

Let me say something in favour of lists:
a) They have simple built-in syntax. Changing the [1,2,3] syntax to use 
a type class will make types even more problematic for beginners... 
Anyway, it won't happen soon.
b) They have a very low constant factor.
c) They are perfectly suited for many tasks. When I write something 
like this:
 > readFile "foo" >>= print . sum . map (product . words) . lines
Then lists are *exactly* what I want. Incidentally, code like this 
accounts for a large part of my use of lists.
I often think of a list as a ForwardIterator from C++'s STL. I agree 
that a singly-linked list is often a bad idea as a data structure for a 
sequence, but we use lists much more often that non-Haskell programmers 
use sequences. Most of our lists are just iterators or streams.

About your Stream module: I don't see the point - I thought you already 
had an instance for Prelude.[] in your Collections module?

> I would
> propose the following time bounds:
>
> Defaults for Sequences:
>   O(logN) for all operations, except
>   O(1) for "atomic queries" (is_empty, first, last, size (or length))

Why are we arguing about "default running times"? It's not like they 
have any observable effect outside the documentation. Lists have been 
used a lot in Haskell, and they will continue to be used a lot. Lists 
are the most "normal" sequences in Haskell, so why shouldn't the 
running time of operations on other sequences be defined relative to 
lists? In fact, I'd say that I should get the default running times 
"for free" and different (in many cases, asymptotically better) running 
times if I am willing to pay a constant factor for that.

Sorry for the long post, but I've followed the discussion long enough, 
and it's always tempting to add my 0.02 euros, so I finally couldn't 
resist anymore...

Cheers,

Wolfgang



More information about the Libraries mailing list