如何比较 Haskell 中的非“Eq”类型?

tim*_*tam 1 haskell functional-programming

加载以下模块时出现错误:

没有因使用“==”而产生的 (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
Run Code Online (Sandbox Code Playgroud)

Wil*_*sem 5

您可以使用模式匹配

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
Run Code Online (Sandbox Code Playgroud)

但是您也可以创建类型类Planet的实例Eq。如果你只是想检查两个Planets 是否相同,如果你使用相同的数据构造函数,你可以让 Haskell 用一个deriving子句来实现:

data Planet
  = Mercury
  | Venus
  | Earth
  | Mars
  | Jupiter
  | Saturn
  | Uranus
  | Neptune
  deriving Eq
Run Code Online (Sandbox Code Playgroud)

  • @timtam FWIW 我有与 duplode 不同的观点:我会 100% 导出 `Eq` ——以及 `Ord` 和 `Enum`。然后我会制作一个“Map Planet Double”,其中包含“myPlanetMap = M.fromList (zip [Mercury .. Neptune] [mercury, venus, Earth, {- ... -}, neptune])”,然后编写`行星上的年龄秒 = (myPlanetMap !planet) * 秒`。 (3认同)
  • @timtam 使用模式匹配实现“ageOn”确实更干净。您通常*还*希望拥有 `Eq` 实例,因为它在其他情况下可能很有用(任意示例:[`group`](https://hackage.haskell.org/package/base-4.14. 1.0/docs/Data-List.html#v:group) 和 [`elem`](https://hackage.haskell.org/package/base-4.14.1.0/docs/Data-List.html#v:elem )对列表元素有一个 `Eq` 约束)。 (2认同)