gpt4 book ai didi

haskell - 为特定构造函数创建实例类

转载 作者:行者123 更新时间:2023-12-02 16:48:51 24 4
gpt4 key购买 nike

假设我有以下数据:

data A
= B Int
| C Float
| D A

如果我想导出 Eq,但更改输出,以便使用构造函数 D 比较两个项目始终相等,有没有办法在不实现它的情况下做到这一点对于所有其他构造函数?对于其他情况,我想派生默认的 Eq 实现。

我想要实现的目标是

instance Eq A where
(D _) == (D _) = True
_ == _ = undefined -- Use default eq

最佳答案

没有直接的方法可以将 GHC 生成的默认 Eq A 实例合并到您自己的 Eq A 实例中。问题在于,实例代码的生成与定义这些实例的过程相关联——生成默认 Eq A 代码的唯一方法是实际生成唯一的 Eq A 实例,一旦实例生成,您就无法真正更改它。即使使用 GHC“派生”相关的扩展,我也看不出有任何方法可以解决这个问题。

但是,您可以使用 generic-deriving 包提供的默认 Eq 实例的重新实现。一些序言:

{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics
import Generics.Deriving.Eq -- from package generic-deriving

使用派生的Generic实例定义您的数据类型:

data A
= B Int
| C Float
| D A
deriving (Generic)

然后,定义一个 GEq 实例,用于实现 D 构造函数的特殊情况,同时遵循其余部分的默认实现。

instance GEq A where
D _ `geq` D _ = True
x `geq` y = x `geqdefault` y

最后,定义一个使用此通用相等类的 Eq 实例。

instance Eq A where
(==) = geq

之后,一切都应该按预期工作:

> D (B 10) == D (B 20)
True
> B 10 == B 20
False
>

但是,采纳评论中的建议可能更合理,并且:

  1. 按照@malloy 的建议进行操作。您尝试定义的操作实际上并不是 (==),那么为什么需要将其命名为 (==) 呢?只需派生常用的 Eq 实例并编写一个单独的函数即可避免不必要的递归:

    equalClasses :: A -> A -> Bool
    equalClasses (D _) (D _) = True
    equalClasses x y = x == y
  2. 如果您确实想使用 (==),我认为使用 @luqui 建议的 newtype 可能是最惯用的方法:

    data A'
    = B Int
    | C Float
    | D A'
    deriving (Eq)

    newtype A = A A'

    instance Eq A where
    A (D _) == A (D _) = True
    A x == A y = x == y

关于haskell - 为特定构造函数创建实例类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55426663/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com