Mad*_*ote 5 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
Run Code Online (Sandbox Code Playgroud)
给出错误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
Run Code Online (Sandbox Code Playgroud)
工作正常(至少我开始理解错误),但是为什么我需要该约束?我正在尝试学习,所以“为什么”对我来说非常重要。
您的原始定义,说CouldBe m是他的一个实例Eq为任何类型m,甚至一个不具有一个Eq实例。但是,如果是这样,您就必须找到一种Is x == Is y无需使用的定义方法x == y(因为您不需要m拥有Eq实例,x == y因此不一定要定义它。)
作为一个具体示例,它可以防止您编写类似
Is (+3) == Is (* 5) -- (+3) == (*5) is undefined
Run Code Online (Sandbox Code Playgroud)
添加约束可确保CouldBe仅在还可以比较包装类型的情况下才可以比较两个值。
一个“有效”但微不足道的实例,没有添加约束:
instance Eq (CouldBe m) where
Is x == Is y = True
Lost == Lost = True
_ == _ = False
Run Code Online (Sandbox Code Playgroud)
CouldBe m只要两个值共享相同的数据构造函数,它们就相等,而与包装值无关。没有尝试使用x或y根本没有尝试使用,因此它们的类型可以不受限制。
用引号引起来是“有效的”,因为此定义可能违反在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
Run Code Online (Sandbox Code Playgroud)
发生冲突是因为Is 3 == Is 5这是正确的,但让f = couldbe 0 id。然后f (Is 3) == f (Is 5)评估3 == 5哪个为假。
它是否实际上是违反行为取决于是否存在couldbe可以在“ CouldBe值内”看到值的函数。
| 归档时间: |
|
| 查看次数: |
57 次 |
| 最近记录: |