[英]How is Ratio implemented in Haskell?
这是我一段时间以来一直困惑的事情,我不知道如何能够更多地了解它。 假设我有以下程序:
main :: IO ()
main = do
x <- liftM read getLine
y <- liftM read getLine
print (x % y)
如果我用输入6
和2
运行它,它将打印3 % 1
。
在什么时候简化发生(即由gcd划分)? 它是在show
实施的吗? 如果是这样,那么理性的基本表示仍然是6 % 2
? 如果没有,那么(%)
是否进行简化? 我的印象是(%)
是一个数据构造函数,那么数据构造函数除了“构造”之外还会做什么呢? 更重要的是,我将如何实际使用自己的数据构造函数进行类似的操作?
我感谢任何关于这个主题的帮助。
Ratio
实际上是在GHC.Real
实现的(显然在GHC上),定义为
data Ratio a = !a :% !a deriving (Eq)
刘海只是严格要求。 如您所见,函数%
不是数据构造函数,但是:%
是。 由于您不应该直接构造Ratio
,因此使用%
函数,它调用reduce。
reduce :: (Integral a) => a -> a -> Ratio a
{-# SPECIALISE reduce :: Integer -> Integer -> Rational #-}
reduce _ 0 = ratioZeroDenominatorError
reduce x y = (x `quot` d) :% (y `quot` d)
where d = gcd x y
(%) :: (Integral a) => a -> a -> Ratio a
x % y = reduce (x * signum y) (abs y)
该规则是,如果运营商是冒号命令:
,那么它是一个构造函数,否则它只是一个普通的操作人员。 实际上,这是Haskell标准的一部分,所有类型的运算符都必须以冒号作为它们的第一个字符。
您可以查看源代码以便自己查看:
instance (Integral a) => Num (Ratio a) where
(x:%y) + (x':%y') = reduce (x*y' + x'*y) (y*y')
(x:%y) - (x':%y') = reduce (x*y' - x'*y) (y*y')
(x:%y) * (x':%y') = reduce (x * x') (y * y')
negate (x:%y) = (-x) :% y
abs (x:%y) = abs x :% y
signum (x:%_) = signum x :% 1
fromInteger x = fromInteger x :% 1
reduce :: (Integral a) => a -> a -> Ratio a
reduce _ 0 = ratioZeroDenominatorError
reduce x y = (x `quot` d) :% (y `quot` d)
where d = gcd x y
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.