
Hi Salvatore On Thu, May 22, 2008 at 11:01:01AM +0200, Salvatore Insalaco wrote:
Consider
let x = Cd ... forkIO $ ( do something with x } -- (1) print x -- (2)
How can ghc know when running line (2) that (1) hasen't changed the record? I see two solutions: a) give the forked process a copy (Then my design will collapse) but this is expensive to copy data without knowing you ned to b) use pointers and replace x ony on updating. Thus if (1) changes the title a new struct wil be created poiting to the old list but a new title String. line (2) doesn't have to care at all.
GHC knows that because in Haskell isn't possible to "update" x. x is not a variable, it's a binding. To put it simply: with IORefs (and STRefs, MVars, ...) you have references to values that you can change (inside their respective monads), much like variables, but data declarations are values, not references to values (even if GHC stores them as pointers you cannot treat them as such), so you cannot update it. Sorry - maybe I'm unable to express using the correct terminology.. So I'll just give a small example how I think it could magically work?
data CD = CD { title :: String, tracks :: [ Track ] } data Track = Track { track :: String, cd :: CD } data PDB = PDB { cds :: Set CD, tracks :: Set Track } Let's fill the database with 1 track and a cd: 0x3 = pointer to DB rec 0x1: adress of CD 0x5: adress of Track 0x4, 0x9, 0x9: start adress of linked list connected by pointers.. In the final solution should use finger trees or such to speed up deletion / replacing elements 0x3 database: 0x8 cds : tuple1 0x1 : (0x6 "My song") (0x4 [ 0x5, ... ]) ^ pointer to str ^ pointer to track list, 0x5 = pointer to track 0x9 tracks: tuple1 0x5 : ( 0x7 "track 1") 0x1 ^ reference to cd Now I query the track, and "update" it (replacing the title).. It's a little bit tricky, because when updating the track I need to update the cd as well (circular referency). All new pointers are starting from 0x20 So in haskell it would look like this: let updatedCd = 0x22 CD (0x6 "My song") (0x20 ( 0x23 : ...) updatedTrack = 0x23 Track ( 0x21 "updated track title" ) 0x22 in (0x27) DB (0x24 (updatedCd:otherCds)) (0x25 (updatedTrack:otherTracks)) Now my new address to access the database is 0x25. So pretty every adress has been changed but 0x6, ..., otherCds and otherTracks A query running using db 0x3 will not notice any change on its snapshot. Are these actions called rebinding? Of course if you have a lot of relations writing this let in will become tedious and error prone.. That's why I'd like to use template haskell to automatically derive it. Thanks for listening Marc Weber