Another possibility would be to keep your definition for Location, but switch to:
data Item a = Item a
type ItemDB = Map Item Location
...and use a recursive lookup to find the location of an item contained within another. This is quite a bit simpler, but whether it's preferable probably depends on whether your more common lookup is "where is item x?" vs. "what's at location y?"
Sometimes relational is the way to go, but it's always worth looking for other options. :) The idiomatic preference, I think, would be to separate the nesting structure from the object data. The item containment graph sounds like a RoseTree, and since location is always inherited, that can just be a Map.import qualified Data.Map as Mdata Rose a = Rose a [Rose a] deriving (Eq, Show)data Item a = Item a deriving (Eq, Show)type ItemGraph a = Rose (Item a)type ItemDB k a = M.Map k (ItemGraph a)>>> let ex_itemdb = M.fromList [("a", Rose (Item 1) [Rose (Item 2) []])]>>> M.lookup "a" ex_itemdbJust (Rose (Item 1) [Rose (Item 2) []])>>> let roseContains i (Rose x xs) = i == x || any (roseContains i) xs>>> let isItemAt i l idb = maybe False id $ roseContains i <$> M.lookup l idb>>> isItemAt (Item 2) "a" ex_itemdbTrue>>> let swapLoc l1 l2 idb = let {i1 = M.lookup l1 idb; i2 = M.lookup l2 idb} in maybe (M.delete l1) (M.insert l1) i2 . maybe (M.delete l2) (M.insert l2) i1 $ idb>>> let moved = swapLoc "a" "b" ex_itemdb>>> isItemAt (Item 2) "a" movedFalse>>> movedfromList [("b",Rose (Item 1) [Rose (Item 2) []])]There are quite a few unfinished pieces here, but hopefully it gets you thinking in new directions!On Tue, Jun 28, 2016 at 11:39 AM, martin <martin.drautzburg@web.de> wrote:Hello all,
I recently tried to model "Items", where an Item can either be inside another Item or at a certain location. I started
like this:
data Location i l = At l
| In (Item i l)
deriving (Eq, Show)
data Item i l = Itm i (Location i l)
deriving (Eq, Show)
type ItemDb i l = [Item i l]
ex_itemdb = let i1 = Itm 1 (At "a")
i2 = Itm 2 (In i1)
in [i1, i2]
Now I wanted to move Item 1 to a different location using this code:
moved = fmap f ex_itemdb
where
f (Itm 1 (At "a")) = (Itm 1 (At "b"))
f x = x
Not this does not do what I want. I get
-- *Main> ex_itemdb
-- [Itm 1 (At "a"),Itm 2 (In (Itm 1 (At "a")))]
-- *Main> moved
-- [Itm 1 (At "b"),Itm 2 (In (Itm 1 (At "a")))]
While Item 1 has moved to "b" Item 2 still claims to be in an "Itm 1 (At "a")". I understand what's going on here and
coming from a DB background I can see that the redundant data is the root of the problem.
I can model this in a relational way such that the redundancy is avoided. But maybe there is a more haskellish/idiomatic
way to acomplish this.
Is there?
_______________________________________________
Beginners mailing list
Beginners@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners