[Fwd: Re: Maps]
apfelmus
apfelmus at quantentunnel.de
Tue Jan 8 15:09:52 EST 2008
Christian Maeder wrote:
> So here's an approximation of my problem. I have a map of objects,
> possibly aggregated from different sources. They have (in a case of
> medium complexity) type (t,u) where the t represents the source and u
> represents the position within that source.
>
> I need to efficiently represent ranges of objects to be viewed or
> deleted from this map, in such a way that the map library can extract or
> delete them quickly. But I might have, say, only a t value, and no
> values of u available.
If you can specify unbounded ranges like None and All,
(a < t < b, All)
would do the trick (together with the usual ordering on pairs). You can
probably retrofit them on any existing data type that expresses
sets/intervals/ranges of values.
data Universal r = None | Concrete r | All
instance Ranged r => Ranged (Universal r) where
range x y = ...
union All _ = All
...
> Also, I'm sort of curious: in C/C++/Java/etc, you can produce a Dense
> type which has:
>
> instance (Eq, Ord, Bounded) Dense
> between :: Dense -> Dense -> Dense -- if a < b then a < between a b < b
>
> This is sort of a lie: between is not referentially transparent, in that
> two calls to (between a b) may produce results that aren't ==.
>
> Still, the efficiency is impressive:
> ==, >, <, etc are O(1)
> 'between' is O(log n) where n Dense's are currently live. You can
> actually make it O(1), but the constant is big, so people don't.
> total space usage is O(n) integers of 2(log n) bits each
I assume the O(1) are O(log n) in "reality" but that n < 2^32 because
they are machine word integers?
> Is there any way to even approach this in Haskell?
Well, the first thing to try is to just use a constructor for between :
data Dense = First | Between Dense Dense | Last
deriving (Eq)
with some clever Ord instance. However, the specification is not
complete, what should
let
half = between a b
q1 = between a half
q3 = between half b
in
compare (between q1 q3) half
be? If it doesn't matter at all, you can probably use the Stern-Brocot
tree <http://en.wikipedia.org/wiki/Stern-Brocot_tree> i.e.
between (a :/ b) (c :/ d) = (a + b) :/ (c + d)
with the usual ordering on rational numbers.
But you probably won't get the same performance with that: the number of
Between constructors or the size in bit of the
denominators/numerators grows linearly with the number of between
operations. This is unavoidable since there are ~ 2^k values that can
be represented with k applications of between . To get better
performance, you have drop referential transparency and exploit that
only a tiny fraction (namely n ) of these possible 2^k will ever come
into existence.
Regards,
apfelmus
More information about the Libraries
mailing list