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

问题描述 投票:5回答:1
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 

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

haskell constraints typeclass
1个回答
7
投票

你原来的定义说CouldBe m是任何类型Eqm实例,甚至是没有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

两个x值相等,只要它们共享相同的数据构造函数,无论包装值如何。没有尝试使用yhttp://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Eq.html,因此它们的类型可以不受约束。

“有效”在引号中,因为这个定义可能违反了CouldBe定义的替代法。假设你有一个可以拉开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这样的函数的存在,它可以看到qazxswpoi值的“内部”。

© www.soinside.com 2019 - 2024. All rights reserved.