En fait, il semble qu' fix (* 0) == 0
fonctionne uniquement pour les Integer
, si vous exécutez fix (* 0) :: Double
ou fix (* 0) :: Int
, vous obtenez toujours ***Exception <<loop>>
C'est parce que dans instance Num Integer
, (*)
est défini comme (*) = timesInteger
timesInteger
est définie en 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 y x
-- no S# as first arg from here on
timesInteger (Jp# x) (Jp# y) = Jp# (timesBigNat x y)
timesInteger (Jp# x) (Jn# y) = Jn# (timesBigNat x y)
timesInteger (Jp# x) (S# y#)
| isTrue# (y# >=# 0#) = Jp# (timesBigNatWord x (int2Word# y#))
| True = Jn# (timesBigNatWord x (int2Word# (negateInt# y#)))
timesInteger (Jn# x) (Jn# y) = Jp# (timesBigNat x y)
timesInteger (Jn# x) (Jp# y) = Jn# (timesBigNat x y)
timesInteger (Jn# x) (S# y#)
| isTrue# (y# >=# 0#) = Jn# (timesBigNatWord x (int2Word# y#))
| True = Jp# (timesBigNatWord x (int2Word# (negateInt# y#)))
Regardez le code ci-dessus, si vous exécutez (* 0) x
, alors timesInteger _ (S# 0#)
correspondent à de sorte qu' x
ne seraient pas évalués, tandis que si vous exécutez (0 *) x
, puis lors de la vérification si timesInteger _ (S# 0#)
matchs, x serait évalué et provoquer une boucle infinie
Nous pouvons utiliser code ci-dessous pour le tester:
module Test where
import Data.Function(fix)
-- fix (0 ~*) == 0
-- fix (~* 0) == ***Exception<<loop>>
(~*) :: (Num a, Eq a) => a -> a -> a
0 ~* _ = 0
_ ~* 0 = 0
x ~* y = x ~* y
-- fix (0 *~) == ***Exception<<loop>>
-- fix (*~ 0) == 0
(*~) :: (Num a, Eq a) => a -> a -> a
_ *~ 0 = 0
0 *~ _ = 0
x *~ y = x *~ y
Il y a quelque chose d'encore plus intéressant, dans GHCI:
*Test> let x = fix (* 0)
*Test> x
0
*Test> x :: Double
*** Exception: <<loop>>
*Test>