On 15/09/10 10:13, Jeroen van Maanen wrote:
The past year I have been working on a port of my machine learning project
named LExAu from Java to Haskell. I'm still very glad I took the jump, because
the complexity curve appears to be log shaped rather than exp shaped. In one
year I almost got to the functionality that had taken me five years to produce
in Java (of course it helped a lot that I had a working prototype this time).
There is one thing that still bothers me though: when I write seq or $! it
doesn't seem to have any effect!
Currently I am trying to add some exception handling to help me debug the system, but the
code that I managed to produce depends on the logging statement to produce the desired
result. :-( It looks like this, and only works when I uncomment the line '-- logger
"Check sum": [...]', otherwise the exception is caught by the try around the
body of the thread that this code runs in:
do logger "Received update" [showString label, logs update]
result<-
try $!
do maybeUpdatedModel<- return $ f update startModel
theCheckSum<- return $ liftM checkSum maybeUpdatedModel
-- logger "Check sum" [showString label, shows theCheckSum]
return $! seq theCheckSum maybeUpdatedModel
maybeNextModel<-
case result of
Right theMaybeNextModel -> return theMaybeNextModel
Left exception ->
do let exc :: SomeException
exc = exception
logger "Exception" [showString label, shows exception]
return Nothing
logger "Maybe next model" [showString label, logs maybeNextModel]
For more context see:
http://lexau.svn.sourceforge.net/viewvc/lexau/branches/totem/src/LExAu/Pipeline/Concurrent.hs?revision=326&view=markup
after line 241.
Can someone explain why a few showStrings a shows and a putStrLn are more
effective in forcing the check sum to be computed (which necessarily evaluates
the complete updated model and reveals the lurking exception) than the seq on
the line just below the logging statement?
I just looked at your code for a second time and I think I know. Here's
my guess:
It's all about the types, and weak head normal form. The "theCheckSum"
item has type Maybe a, and you are looking for an exception in the "a"
part that's wrapped by Maybe (I presume: the Just/Nothing is determined
by the function "f", not "checkSum"). When you use seq or $!, you only
evaluated to weak head normal form, For something of type "Maybe a",
that's only the Just/Nothing part. Forcing that aspect to be evaluated
only requires some evaluation of the function "f", and the checkSum
function doesn't need to be applied, even if it is a Just value.
However, your shows function digs deeper and evaluates the whole thing,
so hence it will trigger the error where seq and $! won't.
So, if I'm right, you need to change your function to make sure to
evaluate the checksum itself. The deepseq package on Hackage may help
here (use the deepseq function in place of seq:
http://hackage.haskell.org/packages/archive/deepseq/1.1.0.0/doc/html/Control-DeepSeq.html).
I'm a little suspicious of the code as a whole though: why does checkSum
throw an exception rather than returning a Maybe value? Or is it an
exception somehow outside of your control?
Another thing:
x <- return $ blah
in a do block is bad style, and can always be replaced with:
let x = blah
Note that there is no "in" needed with let statements in do blocks (that
confused me when first learning Haskell).
Hope that helps,
Neil.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe