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

rob*_*r78 3 haskell

我有一个自定义数据类型,我想比较一下。

data Tile = Wall | Ground | Storage | Box | Blank
Run Code Online (Sandbox Code Playgroud)

我想要做 instance-of-tile == Box

我试过==像这样

tileToInteger :: Tile -> Integer
tileToInteger tile 
  | tile == Blank || tile == Wall = 1
  | otherwise = 2
Run Code Online (Sandbox Code Playgroud)

我也尝试过

tileToInteger :: Eq => Tile -> Integer
Run Code Online (Sandbox Code Playgroud)

来自的错误消息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
Run Code Online (Sandbox Code Playgroud)

这是完整的示例代码

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

背景

Wil*_*sem 7

错误

No instance for (Eq Tile) arising from a use of ‘==’
Run Code Online (Sandbox Code Playgroud)

说您(==)与两个Tiles 一起使用,但是编译器未找到Eq Tile(==)Tiles 定义函数的实例。

您可以使其成为Eqtypeclass的实例:

data Tile = Wall | Ground | Storage | Box | Blank deriving Eq
Run Code Online (Sandbox Code Playgroud)

如果您自动获得Eq,然后哈斯克尔考虑的两个对象Tile相等给出的数据构造(WallGround,...)是相同的,并且其所有参数都是相同的。由于您Tile数据类型的数据构造函数没有参数,因此这仅意味着Wall等于WallGround等于Ground等。

tileToInteger但是,在您的函数中,您根本不需要使用(==),可以使用模式匹配 [Haskell-wiki],例如:

tileToInteger :: Tile -> Integer
tileToInteger Blank = 1
tileToInteger Wall = 1
tileToInteger _ = 2
Run Code Online (Sandbox Code Playgroud)

您可以使用模式匹配(==)为实现的功能Tile,例如:

instance Eq Tile where
    Wall == Wall = True
    Ground == Ground = True
    Storage == Storage = True
    Box == Box = True
    Blank == Blank = True
    _ == _ = False
Run Code Online (Sandbox Code Playgroud)

然而,以上内容等同于deriving Eq将要执行的操作,因此通常,Eq如果Tile以不同的方式将两个s视为等效,则通常只能手动执行。