具有类型构造函数的类型类定义的 Haskell 实例

标签 haskell constraints typeclass

data CouldBe a = Is a | Lost deriving (Show, Ord)

instance Eq (CouldBe m) where
  Is x == Is y = x == y 
  Lost == Lost = True 
  _ == _ = False 

给出错误:No instance for (Eq m) arising from a use of ‘==’所以:
instance (Eq m) => Eq (CouldBe m) where
  Is x == Is y = x == y 
  Lost == Lost = True 
  _ == _ = False 

工作正常(至少我开始理解错误),但为什么我需要这个约束?
我正在努力学习,所以“为什么”对我来说非常重要。

最佳答案

您原来的定义是 CouldBe mEq 的一个实例适用于任何类型 m ,即使一个没有 Eq实例。但如果这是真的,你必须找到某种方式来定义 Is x == Is y不使用 x == y (因为你没有要求 m 有一个 Eq 实例,x == y 不一定定义。)

作为一个具体的例子,它阻止你写类似的东西

Is (+3) == Is (* 5)  -- (+3) == (*5) is undefined

添加约束确保您可以比较两个 CouldBe仅当也可以比较包装类型时的值。

没有添加约束的“有效”但微不足道的实例:
instance Eq (CouldBe m) where
  Is x == Is y = True
  Lost == Lost = True
  _ == _ = False

两个CouldBe m只要它们共享相同的数据构造函数,值就相等,而不管包装的值如何。不尝试使用 xy完全,所以它们的类型可以不受约束。

“有效”用引号引起来,因为这个定义可能违反了替代法,定义于 http://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Eq.html .假设您有一个函数可以将 CouldBe 分开值(value):
couldbe :: b -> (a -> b) -> CouldBe a -> b
couldBe x _ Lost = x
couldBe _ f (Is x) = f x

发生违规的原因是 Is 3 == Is 5会是真的,但让 f = couldbe 0 id .然后f (Is 3) == f (Is 5)计算结果为 3 == 5这是错误的。

实际上是否违规取决于是否存在类似 couldbe 的函数。可以看到“内部”一个 CouldBe值(value)。

关于具有类型构造函数的类型类定义的 Haskell 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55048943/

相关文章:

haskell - 使用 yesod 生成动态表单

haskell - GHC 无需 Root 即可安装

ios - 当我使用约束时 AVMakeRect 返回工作值

Scalaz Bind[Seq] 类型类

Scala 类型类

haskell `stack` 用于卸载/清理的命令?

haskell - 在 Haskell 中运行测试和测试用例的所有组合

ios - 约束 uiimageview 以保持宽高比并根据设备大小进行扩展

python - 控制洗牌距离

haskell - 如何使用实例组织 Haskell 模块 : stick to data type vs type class?