
On Tue, Sep 28, 2010 at 10:06 AM, Romain Demeyer
Let's a function "do_job", the function to execute by the threads (the workers) : do_job :: (b -> a) -> b -> Inbox a -> IO () do_job f input inbox = do { value <- return (f input) ; atomically ( writeMsg inbox value ) }
First of all, note that do v <- return (f x) ... is exactly the same as do let v = f x ... Now, if you want to evaluate your value to WHNF (Weak Head Normal Formal), you may use
do_job :: (b -> a) -> b -> Inbox a -> IO () do_job f input inbox = do value <- evaluate (f input) atomically (writeMsg inbox value)
This will work pretty well if your value is simple (eg. an Int) but not so well if it is complex (eg. a Data.Map) because it will evaluate only as much as 'seq'. You may than use the 'deepseq' package:
import Control.DeepSeq
do_job :: NFData a => (b -> a) -> b -> Inbox a -> IO () do_job f input inbox = let value = f input in value `deepseq` atomically (writeMsg inbox value)
This will fully evaluate the structure before calling 'writeMsg'.
That's what we want, but what is the explanation of this behavior? STM is designed to be optimistic, not blocking. So, does it means that the "value" is evaluated at "commit-time"? Do you know some problems that are related or do you know some works that can be useful at this subject?
Those values are pure, so if you say writeMsg inbox (f x) then internally a thunk is created referencing 'f' and 'x', and a pointer to that thunk is atomically commited. Just like the rest of the program. The value is not being evaluated by STM at all, as your STM functions don't need the value. In your program is evaluating when you print the answer in the main thread, as printing requires the value of the computation. If you didn't print, nothing would be computed at all. Lazy =). HTH, -- Felipe.