为什么 Haskell 在将文字转换为我的类型时挂起?
Why does Haskell hang upon casting a literal to my type?
我已经为 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
当我试图将一个负数 'cast' 转换为 SafeRational
时出现问题。 Haskell 挂了,好像进入了无限倒退。正数和零不会表现得很奇怪,只有小于零的数字才会。因为我使用 Haskell 作为数学工具,所以我不经常玩 class 声明,我担心我不知道如何调试问题。有人可以解释一下吗?
*GHCi> 0-2 :: SafeRational -- makes Haskell sad
_
即使没有启用任何警告,我也会在将代码片段加载到 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
?
其他评论意见:
您可以通过以下方式定义节目:
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算子应用):
The special form -e denotes prefix negation, the only prefix operator in Haskell , and is syntax for negate (e)
. The binary -
operator does not necessarily refer to the definition of -
in the Prelude; it may be rebound by the module system. However, unary -
will always refer to the negate
function defined in the Prelude. There is no link between the local meaning of the -
operator and unary negation.
所以-2
转化为negate (fromInteger (2 :: Integer))
.
这是 Haskell 的奇怪和讨论的功能:https://www.haskell.org/haskellwiki/Unary_operator https://ghc.haskell.org/trac/haskell-prime/wiki/NegativeSyntax
我已经为 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
当我试图将一个负数 'cast' 转换为 SafeRational
时出现问题。 Haskell 挂了,好像进入了无限倒退。正数和零不会表现得很奇怪,只有小于零的数字才会。因为我使用 Haskell 作为数学工具,所以我不经常玩 class 声明,我担心我不知道如何调试问题。有人可以解释一下吗?
*GHCi> 0-2 :: SafeRational -- makes Haskell sad
_
即使没有启用任何警告,我也会在将代码片段加载到 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
?
其他评论意见:
您可以通过以下方式定义节目:
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算子应用):
The special form -e denotes prefix negation, the only prefix operator in Haskell , and is syntax for
negate (e)
. The binary-
operator does not necessarily refer to the definition of-
in the Prelude; it may be rebound by the module system. However, unary-
will always refer to thenegate
function defined in the Prelude. There is no link between the local meaning of the-
operator and unary negation.
所以-2
转化为negate (fromInteger (2 :: Integer))
.
这是 Haskell 的奇怪和讨论的功能:https://www.haskell.org/haskellwiki/Unary_operator https://ghc.haskell.org/trac/haskell-prime/wiki/NegativeSyntax