【问题标题】:Haskell instance of typeclass definition with type constructor具有类型构造函数的类型类定义的 Haskell 实例
【发布时间】:2019-03-08 02:01:18
【问题描述】:
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】:

    您的原始定义说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 值:

    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 值的函数。

    【讨论】:

    • 太棒了。可以理解和注意!谢谢
    • 我认为如果你要称这个微不足道的实例为“有效”,你应该指出,如果你不为客户提供一种观察内部价值的方法,这只会遵循 Eq 替代定律是。更有可能的是,这些值是公开的,因此普通实例在技术上可以编译,但不像 Eq 实例那样表现。
    • 谢谢;我想我以前从未注意到替代定律。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多