7

Is there an efficient fixed-size list library in Haskell? I think the IArray interface is somewhat complicated when one only wants arrays indexed by natural numbers [including zero]. I want to write code like

zeroToTwenty :: Int -> FixedList Int
zeroToTwenty 0 = createFixedList 21 []
zeroToTwenty n = zeroToTwenty (n-1) `append` n

my naive solution is below.

Edit: Sorry for the lack of context; I want a datastructure that can be allocated once, to avoid excessive garbage collection. This was in the context of the merge routine for merge sort, which takes two sorted sublists and produces a single sorted list.

4
  • 1
    What is it you expect from this data type that list don't give you? Is it O(1) indexing? And what are you willing to trade away to get O(1) indexing? Commented Jun 14, 2011 at 13:10
  • Well, I still don't know what operations you expect. Something that is allocated in one go also has to be filled with contents on one go in Haskell. Unless you want to use a mutable data structure. Commented Jun 14, 2011 at 20:20
  • @augustss The diffarray internally uses a monad (according to Wikipedia), so elementwise substitution is constant time. Commented Jun 15, 2011 at 8:09
  • 1
    Difference arrays have very weird complexity when used in a persistent way. Commented Jun 15, 2011 at 12:00

4 Answers 4

6

How about using the vector package? It provides very efficient growable vectors with a list-like interface, and O(1) indexing.

Sign up to request clarification or add additional context in comments.

5 Comments

Sorry for being lazy; it says cons is O(n) on the package page -- this isn't quite what I want (though I'm sure I'll use vector now that I know about it).
Indeed, cons is O(n). However, you can efficiently create a fixed-sized vector via replicate and other combinators. Just stay away from the list-ish cons.
Well, I wanted a list-ish API :), maybe I'll just combine it with what I have below?
@gatoatigrado, strange that you would want cons when you were specifically looking for a fixed-size list library.
@luqui The point is that previous code could be refactored painlessly if you know the final size of the list. In general one would probaly want a power-of-2 reallocation scheme.
2

I would probably use Vector as Don Stewart suggests, but you can use a list-like interface with IArray by using ListLike.

2 Comments

I hope that the asker knows that wrapping an array by ListLike will not magically provide an O(1)-time cons. (See the asker’s comments on Don Stewart’s answer.)
@Tsuyoshi Ito: this is a very good point. ListLike is just an interface; the performance characteristics of the implementation don't change. If both cons and indexing are important, I might suggest Data.Sequence. But more context is needed to make a real suggestion.
1

You might consider using a finger tree. It offers amortized O(1) cons, snoc, uncons, and unsnoc, and O(log n) split.

Comments

0

Here's my naive solution,

import Data.Array.Diff
newtype FixedList a = FixedList (Int, (DiffArray Int a))
createFixedList n init = FixedList (0, array (0, n - 1) init)
append (FixedList (curr, array)) v = FixedList (curr + 1, array // [(curr, v)])

instance Show a => Show (FixedList a) where
    show (FixedList (curr, arr)) = show $ take curr (elems arr)

2 Comments

BTW, diff arrays are deprecated, and their performance is pretty poor as well.
@Don Stewart: Thanks! Is Vector the best replacement?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.