如何在Haskell中比较自定义数据类型

时间:2019-06-01 12:22:36

标签: haskell

我有一个要比较的自定义数据类型。

data Tile = Wall | Ground | Storage | Box | Blank

我想做instance-of-tile == Box

我尝试像这样使用==

tileToInteger :: Tile -> Integer
tileToInteger tile 
  | tile == Blank || tile == Wall = 1
  | otherwise = 2

我也尝试过

tileToInteger :: Eq => Tile -> Integer

来自stack build的错误消息是

No instance for (Eq Tile) arising from a use of ‘==’
    • In the first argument of ‘(||)’, namely ‘tile == Blank’
      In the expression: tile == Blank || tile == Wall
      In a stmt of a pattern guard for an equation for ‘tileToInteger’: tile == Blank || tile == Wall

这是完整的示例代码

data Tile = Wall | Ground | Storage | Box | Blank

getTileAtXY :: Integer -> Integer -> Tile
getTileAtXY x y
  | x == 0 && y == 0 = Box
  | otherwise = Ground

tileToInteger :: Tile -> Integer
tileToInteger tile 
  | tile == Blank || tile == Wall = 1
  | otherwise = 2

main :: IO ()
main = print (tileToInteger (getTileAtXY 1 0))

背景

2 个答案:

答案 0 :(得分:7)

错误

No instance for (Eq Tile) arising from a use of ‘==’

假设您将(==)与两个Tile一起使用,但是编译器没有找到Eq Tile的实例,而您在其中为{{1 }}。

您可以将其设为Eq typeclass的实例:

(==)

如果您自动派生Tile,则在数据构造函数(data Tile = Wall | Ground | Storage | Box | Blank deriving EqEq等相同的情况下,Haskell认为Tile的两个对象相等,他们所有的论点都是一样的。由于Wall数据类型的数据构造函数没有参数,因此,这仅意味着Ground等于TileWall等于Wall,等

但是在功能Ground中,根本不需要使用Ground,可以使用pattern matching [Haskell-wiki],例如:

tileToInteger

您可以为(==)的{​​{1}}函数实施模式匹配,例如:

tileToInteger :: Tile -> Integer
tileToInteger Blank = 1
tileToInteger Wall = 1
tileToInteger _ = 2

然而,上述内容等同于(==)的作用,因此通常只有在两个Tile被认为是等效的情况下才手动实现instance Eq Tile where Wall == Wall = True Ground == Ground = True Storage == Storage = True Box == Box = True Blank == Blank = True _ == _ = False

答案 1 :(得分:3)

您可以推导自动进行比较的方法:

data Tile = Wall | Ground | Storage | Box | Blank deriving (Eq)

然后您可以使用==/=比较Tile的相等性和不平等性。