如何比较Haskell中的非“Eq”类型?
加载以下模块时出现错误:
没有因使用“==”而产生的 (Eq Planet) 实例 • 在表达式中:planet == Mercury 在“ageOn”等式的模式守卫的 stmt 中:
如何检查行星是否等于某个行星?
module SpaceAge (Planet(..), ageOn) where
data Planet = Mercury
| Venus
| Earth
| Mars
| Jupiter
| Saturn
| Uranus
| Neptune
mercury :: Float
mercury = 0.2408467
venus :: Float
venus = 0.61519726
earth :: Float
earth = 1.0
mars :: Float
mars = 1.8808158
jupiter :: Float
jupiter = 11.862615
saturn :: Float
saturn = 29.447498
uranus :: Float
uranus = 84.016846
neptune :: Float
neptune = 164.79132
ageOn :: Planet -> Float -> Float
ageOn planet seconds
| planet == Mercury = seconds * mercury
| planet == Venus = seconds * venus
| planet == Earth = seconds * earth
| planet == Mars = seconds * mars
| planet == Jupiter = seconds * jupiter
| planet == Saturn = seconds * saturn
| planet == Uranus = seconds * uranus
| planet == Neptune = seconds * neptune
回答
您可以使用模式匹配:
ageOn :: Planet -> Float -> Float
ageOn Mercury seconds = seconds * mercury
ageOn Venus seconds = seconds * venus
ageOn Earth seconds = seconds * earth
ageOn Mars seconds = seconds * mars
ageOn Jupiter seconds = seconds * jupiter
ageOn Saturn seconds = seconds * saturn
ageOn Uranus seconds = seconds * uranus
ageOn Neptune seconds = seconds * neptune
但是您也可以创建类型类Planet的实例Eq。如果你只是想检查两个Planets 是否相同,如果你使用相同的数据构造函数,你可以让 Haskell 用一个deriving子句来实现:
data Planet
= Mercury
| Venus
| Earth
| Mars
| Jupiter
| Saturn
| Uranus
| Neptune
deriving Eq
- @timtam FWIW I have a different opinion than duplode: I would 100% derive `Eq` -- and also `Ord` and `Enum`. Then I'd make a `Map Planet Double` with something like `myPlanetMap = M.fromList (zip [Mercury .. Neptune] [mercury, venus, earth, {- ... -}, neptune])`, and write `ageOn planet seconds = (myPlanetMap ! planet) * seconds`.
- @timtam Implementing your `ageOn` with pattern matching is indeed cleaner. You'd typically *also* want to have the `Eq` instance, as it can be useful in other situations (arbitrary examples: [`group`](https://hackage.haskell.org/package/base-4.14.1.0/docs/Data-List.html#v:group) and [`elem`](https://hackage.haskell.org/package/base-4.14.1.0/docs/Data-List.html#v:elem) have an `Eq` constraint on the list elements).