joshj
joshj

Reputation: 583

Which container should I use?

I'm new to haskell, and so I'm trying to recreate the following C++ code in haskell.

int main() {
    class MyClass {
        public:
        int a;
        std::string s;
        float f;
    };
    std::vector <MyClass> v;
    LoadSerialized(&v); // don't need haskell equivalent; just reads a bunch of MyClass's and pushes them back onto v
}

Now, I've looked at the various containers in haskell that might work as the std::vector here: there's list, unboxed vector, boxed vector, and some weird usage of foreign pointers like the following:

data Table = Table { floats :: ForeignPtr CFloat
                   , ints   :: ForeignPtr Int    }

newTable :: IO Table
newTable = do
    fp <- S.mallocByteString (floatSize * sizeOf (undefined :: CFloat))
    ip <- S.mallocByteString (intSize   * sizeOf (undefined :: Int   ))
    withForeignPtr fp $ \p ->
        forM_ [0..floatSize-1] $ \n ->
            pokeElemOff p n pi
    withForeignPtr ip $ \p ->
        forM_ [0..intSize-1]   $ \n ->
            pokeElemOff p n n
    return (Table fp ip)

Now, I could implement the C++ code in the way I think is best--being a haskell newbie. Or I could ask people more experienced with the language what the best way is, because to me it looks like there's some nuance going on here that I'm missing. Simply, I want to push a structure containing many datatypes into a haskell container, and I don't care about the order. If it helps, I'm going to read serialized data into the container as you can see with LoadSerialized.

I'm not mixing in C++ code.

(Edit: is it stackoverflow policy to allow censorship of questions through editing (not minor)? It does say "always respect the original author.")

Upvotes: 1

Views: 513

Answers (1)

dave4420
dave4420

Reputation: 47052

If you are writing the whole program in Haskell, Just use a list unless you have a good reason not to. (If you do have a good reason not to, please say what it is and we can help you choose a more appropriate data structure. e.g. random access to a specific list element is O(n) rather than the O(1) of a C++ vector, and updating values in a data structure is different in Haskell.)

If you are mixing Haskell and C++ in the same program, and you need help calling C++ from Haskell, please say.

  • Use lists by default. List operations such as map, foldr and filter can be fused together by the compiler, resulting in more efficient code than you would typically get using a C++ vector.
  • Use an array of some sort if you find yourself needing to lookup an element by index, or wanting to mutate an element at a specific index. See Data.Array, Data.Array.IO, and Data.Array.ST.
  • Use a sequence if you find yourself needing to insert new elements in the middle of the data structure, or at both ends of the structure. See Data.Sequence.

Upvotes: 3

Related Questions