我已经为Rational编写了一个包装器类型,NaN&#是一个除零而不是崩溃的程序。代码编译时没有错误或警告。这是(希望是全部)相关代码:
data SafeRational =
SRatio Rational |
SRatioNaN
instance Show (SafeRational) where
show (SRatio x) = show . fromRational $ x
show SRatioNaN = "NaN"
instance Num (SafeRational) where
(+) (SRatio a) (SRatio b) = SRatio (a+b)
(+) _ _ = SRatioNaN -- Good?
(*) (SRatio a) (SRatio b) = SRatio (a*b)
(*) _ _ = SRatioNaN
signum (SRatio a) = SRatio (signum a)
signum SRatioNaN = SRatio 0
abs (SRatio a) = SRatio (abs a)
abs SRatioNaN = SRatioNaN
fromInteger a = SRatio (fromInteger a)
instance Enum (SafeRational) where
fromEnum (SRatio x) = fromEnum x
fromEnum SRatioNaN = 0
toEnum x = SRatio $ toEnum x
instance Fractional (SafeRational) where
(/) (SRatio a) (SRatio b)
| b == 0 = SRatioNaN
| otherwise = SRatio (a / b)
fromRational a = SRatio a
当我尝试演员时会出现问题。 SafeRational
的负字面数字。 Haskell挂起就好像它已进入无限回归。正数和零不奇怪,只有零以下的数字。因为我使用Haskell作为数学工具,我不经常使用类声明,我担心我不知道如何调试问题。有人请解释一下吗?
*GHCi> 0-2 :: SafeRational -- makes Haskell sad
_
答案 0 :(得分:8)
即使没有启用任何警告,我也会在将代码段加载到ghci(7.8.3)时得到:
SRational.hs:9:10: Warning:
No explicit implementation for
either ‘negate’ or ‘-’
In the instance declaration for ‘Num SafeRational’
即。必须定义一个。它们的默认定义是相互递归的:
x - y = x + negate y
negate x = 0 - x
同样启用-Wall
,你会发现另一个错误:
SRational.hs:26:5: Warning:
Pattern match(es) are non-exhaustive
In an equation for ‘/’:
Patterns not matched:
SRatioNaN _
(SRatio _) SRatioNaN
按SRatioNaN
划分任何内容时会发生什么情况,例如0 / SRatioNaN
?
您可以定义show by:
instance Show (SafeRational) where
show (SRatio x) = show x
show SRatioNaN = "NaN"
当另一个-Wall
警告提示时,您(不必要地,丢失信息)会将Rational
转换为Double
。
(+) _ _ = SRatioNaN -- Good?
是的,但是
SRatio a + SRatio b = SRatio (a + b)
_ + _ = SRatioNan
读得更好(恕我直言)。
为什么将文字-2
转换为fromInteger (-2 :: Integer)
?原因在于Haskell Report(3.4运算符应用程序):
特殊形式-e表示前缀否定,Haskell中唯一的前缀运算符,是
negate (e)
的语法。二元-
运算符不一定引用Prelude中-
的定义;它可能会被模块系统反弹。但是,一元-
将始终引用Prelude中定义的negate
函数。-
运算符的本地含义与一元否定之间没有联系。
所以-2
转换为negate (fromInteger (2 :: Integer))
。
这是Haskell的奇怪和讨论的特征:https://www.haskell.org/haskellwiki/Unary_operator https://ghc.haskell.org/trac/haskell-prime/wiki/NegativeSyntax