如何有效地为类型类实例Eq
我制作了以下类来在不同的温度类型之间进行转换:
data Temp = Kelvin Float | Celsius Float |Fahrenheit Float deriving Show
conversionKelvin:: Temp -> Temp
conversionKelvin (Celsius x) = Kelvin (x + 273.15)
conversionKelvin (Fahrenheit x) = Kelvin((x - 32) * 5/9 + 273.15)
conversionKelvin (Kelvin x) = Kelvin x
conversionCelsius:: Temp -> Temp
conversionCelsius (Kelvin x) = Celsius (x - 273.15)
conversionCelsius (Fahrenheit x) = Celsius((x - 32) * 5/9)
conversionCelsius (Celsius x) = Celsius x
conversionFahrenheit:: Temp -> Temp
conversionFahrenheit (Celsius x) = Fahrenheit (x * 9/5 + 32)
conversionFahrenheit (Kelvin x) = Fahrenheit((x - 273.15)*9/5 + 32)
conversionFahrenheit (Fahrenheit x) = Fahrenheit x
到目前为止一切都很好,但是我想实现实例 Eq 和 Ord。我想过将每种类型转换为摄氏度,然后看看哪个更大,但我无法通过编译器。有什么帮助吗?
编辑:这是我在实例化 Eq 的尝试:
instance Eq Temp where
a == b = conversionCelsius(a) == conversionCelsius(b)
instance Eq Temp where
a == b = conversionCelsius(a) == conversionCelsius(b)
它编译但它使haskell进入某种循环(不打印输出)
回答
这导致无限递归
这是因为比较a == b的是这两种Temps,并且比较conversionCelsius(a) == conversionCelsius(b)是再次两者TempS,所以我们永远递归。
要停止递归,您至少需要有一个基本情况,其中Temps之间的比较是通过比较Floats来完成的。一种可能的解决方案如下。
instance Eq Temp where
Celsius x == Celsius y = x == y
a == b = conversionCelsius a == conversionCelsius b
这将直接比较摄氏温度,比较它们的Float值。其他温度会在递归之前转换为摄氏度。递归之后,我们会立即找到基本情况,这样递归就结束了。