I was messing around with fix and after messing around with it I came across some weird behavior, namely that 0 * undefined is *** Exception: Pre
Take the following for example
(if expensiveTest1 then 0 else 2) * (if expensiveTest2 then 0 else 2)
You have to choose a side to evaluate. If expensiveTest2 is an infinite loop, you will never be able to tell whether the right side is 0 or not, so you can't tell whether or not to short circuit the right side, so you never get to look at the left side. You can't check if both sides are 0 at once.
As for whether you can rely on short circuiting to act in a certain way, just keep in mind that undefined and error acts exactly like an infinite loop as long as you don't use IO. Therefore, you can test short circuiting and laziness using undefined and error. In general, short circuiting behavior varies from function to function. (There are also different levels of laziness. undefined and Just undefined may give different results.)
See this for more details.