I have a problem similar to this. However, it involves LOTS of update and I'm not sure IxSet is the solution.
Basically I'm writing an application to optimize a warehouse layout. There is no database or anything; it's just plain data to manipulate and generate a file at the end. A warehouse is made of shelves of different sizes; shelves contains boxes of different sizes; and the goal is to find the best arrangement (or at least, a good one), where to put boxes so they all fit.
The basic model (which doesn't really matter) is :
data Dimension = Dimension {length::Double, width::Double, height::Double}
data Box = Box {boxId :: Int, boxDim:: Dimension }
data Shelf = Shelf {shelfId :: Int, shelfDim :: Dimension, postion :: ... }
Now, the first problem is that there is a shelves graph. Some shelves are back to back. I need to know it because the depth of one shelf can be adjusted (which modify in the opposite way the back shelf). I also need to know the opposite shelf and the next one.
What is the most efficient way to model this?
My first thought is:
data Shelf = Shelf { ... , backShelf :: Maybe Shelf
, frontShelf :: Maybe Shelf
, nextShelf :: Maybe Shelf
}
Now, data are immutable in Haskell, so how can I update a Shelf
? I mean, imagine I have a list of Shelf
's; if I modify one, then I need to update all the copies of it?
My second thought is to use ids instead:
newtype ShelfId = Int
data Shelf = Shelf { ..., backShelfId :: Maybe ShelfId ... }
Or should I use external graphs? Something like
back, front, next :: [(shelfId, shelfId)]
The second problem how to model the fact a box belongs to a shelf.
Possible approaches that come to mind are:
data Box = Box { ..., shelf :: Shelf }
or
data Box = Box { ..., shelfId :: Maybe ShelfId }
or
data Shelf = Shelf { ..., boxes = [Box] }
or
data Shelf = Shelf { ..., boxIds = [BoxId] }
An external graph
boxToShelf :: [(BoxId, ShelfId)]
Also, as I said, the operations involve lots of updates; I might add boxes one by one to each shelf, which can be really inefficient with immutable data.
The other solution I thought would be to use STRef
or equivalent:
data Box = { ..., shelf :: STRef Shelf }
It feels like using pointer, so it's probably no a good idea.
Update
This is not an XY problem neither a toy problem. This is a realworld application for a real warehouse (arount 100 shelves and 3000 of boxes). It needs to be able to draw and load existing data (boxes and their location). The optimisation is only a small part of it and will probably be semi-manual.
So my question is about representing relation between mutable objects not basic combinatory problems.