Actually it seems that fix (* 0) == 0 only works for Integer , if you run fix (* 0) :: Double or fix (* 0) :: Int , you still get ***Exception <<loop>>
This is because in instance Num Integer , (*) is defined as (*) = timesInteger
timesInteger defined in Data.Integer
-- | Multiply two 'Integer's timesInteger :: Integer -> Integer -> Integer timesInteger _ (S# 0#) = S# 0# timesInteger (S# 0#) _ = S# 0# timesInteger x (S# 1#) = x timesInteger (S# 1#) y = y timesInteger x (S# -1#) = negateInteger x timesInteger (S# -1#) y = negateInteger y timesInteger (S# x#) (S# y#) = case mulIntMayOflo# x# y# of 0# -> S# (x# *# y#) _ -> timesInt2Integer x# y# timesInteger x@(S# _) y = timesInteger yx -- no S# as first arg from here on timesInteger (Jp# x) (Jp# y) = Jp# (timesBigNat xy) timesInteger (Jp# x) (Jn# y) = Jn# (timesBigNat xy) timesInteger (Jp# x) (S# y#) | isTrue
Look at the code above, if you run (* 0) x , then timesInteger _ (S# 0#) will match so that x will not be evaluated, and if you run (0 *) x , then when checking if timesInteger _ (S# 0#) x will evaluate and cause an infinite loop
We can use the code below to verify it:
module Test where import Data.Function(fix)
GHCI has something even more interesting:
*Test> let x = fix (* 0) *Test> x 0 *Test> x :: Double *** Exception: <<loop>> *Test>
Alaya Mar 17 '16 at 3:46 2016-03-17 03:46
source share