根据数据的特定部分派生实例

cha*_*ni2 3 haskell

我有以下代码

type Position = (Int,Int)

data CheckError where
    LError :: Position -> LexerError  -> CheckError
    PError :: Position -> ParseError  -> CheckError
    SError :: Position -> StaticError -> CheckError
Run Code Online (Sandbox Code Playgroud)

我需要它来实例,Ord但只需比较Position每个构造函数中的字段.

我得到了这个:

data CheckError where
    LError :: Position -> LexerError  -> CheckError
    PError :: Position -> ParseError  -> CheckError
    SError :: Position -> StaticError -> CheckError
    deriving (Show)

instance Eq CheckError where
    (LError l _) == (LError r _) = l == r
    (LError l _) == (PError r _) = l == r
    (LError l _) == (SError r _) = l == r
    (PError l _) == (LError r _) = l == r
    (PError l _) == (PError r _) = l == r
    (PError l _) == (SError r _) = l == r
    (SError l _) == (LError r _) = l == r
    (SError l _) == (PError r _) = l == r
    (SError l _) == (SError r _) = l == r

instance Ord CheckError where
    compare (LError l _) (LError r _) = l `compare` r
    compare (LError l _) (PError r _) = l `compare` r
    compare (LError l _) (SError r _) = l `compare` r
    compare (PError l _) (LError r _) = l `compare` r
    compare (PError l _) (PError r _) = l `compare` r
    compare (PError l _) (SError r _) = l `compare` r
    compare (SError l _) (LError r _) = l `compare` r
    compare (SError l _) (PError r _) = l `compare` r
    compare (SError l _) (SError r _) = l `compare` r
Run Code Online (Sandbox Code Playgroud)

但我觉得这段代码太重复了.有没有办法告诉Haskell直接与该Position领域进行比较?

小智 7

也许这样?

 instance Eq CheckError where
    a == b = pos a == pos b 
              where 
                pos (LError p _) = p
                pos (PError p _) = p
                pos (SError p _) = p
Run Code Online (Sandbox Code Playgroud)

  • 事实证明,您还可以使用GADT的记录语法.所以`pos`可以免费定义. (2认同)
  • 也就是说,你可以定义`data CheckError where LError :: {pos :: Position,lerr :: LexerError} - > CheckError; PError :: {pos :: Position,perr :: ParseError} - > CheckError; SError :: {pos :: Position,serr :: StaticError} - > CheckError` (2认同)