Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does multiplication only short circuit on one side

I was messing around with fix and after messing around with it I came across some weird behavior, namely that 0 * undefined is *** Exception: Prelude.undefined and undefined * 0 is 0. Which also means that fix (0 *) is *** Exception: <<loop>> and fix (* 0) is 0.

After playing around with it it seems like the reason is because it is non-trivial to make it short circuit in both directions, as that doesn't really make much sense, without some sort of weird parallel computation and start with the first non-bottom returned.

Is this kind of thing seen in other places (reflexive functions that aren't reflexive for bottom values), and is it something I can safely rely on? Also is there a practical way to make both (0 *) and (* 0) evaluate to zero regardless of the value passed in.

like image 584
semicolon Avatar asked Mar 17 '16 00:03

semicolon


Video Answer


1 Answers

Your reasoning is correct. There is an unamb package providing tools for the sort of parallel computation you refer to. In fact, it offers Data.Unamb.pmult, which tries, in parallel, to check whether each operand is 1 or 0, and if so immediately produces a result. This parallel approach is likely to be much slower in most cases for simple arithmetic!

The short-circuiting of (*) occurs only in GHC version 7.10. It came about as a result of changes to the implementation of the Integer type in that GHC version. That extra laziness was generally seen as a performance bug (as it interferes with strictness analysis and can even lead to space leaks in theory), so it will be removed in GHC 8.0.

like image 176
dfeuer Avatar answered Oct 08 '22 02:10

dfeuer