这是我一段时间以来一直困惑的事情,我不知道如何能够更多地了解它。假设我有以下程序:
main :: IO ()
main = do
x <- liftM read getLine
y <- liftM read getLine
print (x % y)
如果我使用输入6
和2
运行此操作,则会打印3 % 1
。
简化发生在什么时候(即gcd划分)?它是否在show
中实施?如果是这样,那么理性的基础表示仍然是6 % 2
?如果没有,那么(%)
会进行简化吗?我的印象是(%)
是一个数据构造函数,那么数据构造函数除了“构造”之外还会做什么呢?更重要的是,我将如何实际使用自己的数据构造函数进行类似的操作?
感谢您对此主题的任何帮助。
答案 0 :(得分:17)
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标准的一部分,所有类型操作符都必须以冒号作为它们的第一个字符。
答案 1 :(得分:7)
您只需查看source即可自行查看:
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