我已经实现了一个有理数的归一化函数normaliseRat::Rat -> Rat,这样所有的Rat 2 4,Rat(-1)(-2)和Rat 1 2都被转换为相同的内部表示。此外,实现了一个函数Rat::Rat-> Rat,给定两个整数,返回一个归一化的Rat。注意:我使用包含函数gcd的Prelude来计算两个整数的最大公约数。
gcd' :: Integer -> Integer -> Integer
gcd' a b = if b == 0 then a else gcd' b (a `mod` b)
data Rat = Rat Integer Integer
normaliseRat :: Rat -> Rat
normaliseRat (Rat num den) =
let commonDivisor = gcd' (abs num) (abs den)
num' = num `div` commonDivisor
den' = den `div` commonDivisor
in Rat (if den < 0 then (-num') else num') (abs den')
createRat :: Integer -> Integer -> Rat
createRat num den = normaliseRat (Rat num den)
-- Adding the Show instance for Rat
instance Show Rat where
show (Rat num den) = show num ++ "/" ++ show den
字符串
这个程序给出了预期的结果。像:
ghci>createRat 2 4
ghci> rat1
1/2
型
现在我想让Rat成为Eq和Ord的一个示例。当然,Rat 2 4 == Rat 1 2应该计算为True。
2条答案
按热度按时间mzsu5hc01#
一种选择是确保
Rat 2 4
不是一个可以构造的值。通过只公开保留规范化的API部分来实现这一点。例如:字符串
这是一种相当标准的技术,您可以使用“smartconstructor”作为搜索词来查找更多的资源。
顺便说一下,我建议派生
Show
示例。如果你想用一种更漂亮的方式来显示有理数,导出一个专门的函数,名为showRat
或类似的。这也是一个常见的做法。ymdaylpp2#
我们知道两个分数 a/B 和 c/d 是相等的,如果 a×d = c×B(假设因子不为零),那么我们可以将
Eq
示例实现为:字符串
我把
Ord
的示例留作练习。这会更复杂,因为它的参数也可以是负的。