如何解决带和不带类型类约束的 Eq 实例
这是我的代数数据类型 (ADT) 的 Eq 实现
data Stateful a =
Advancing a
| Stable a
| Finished a
instance statefulEq :: (Eq a) => Eq (Stateful a)
where
eq (Advancing x) (Advancing y) = eq x y
eq (Stable x) (Stable y) = eq x y
eq (Finished x) (Finished y) = eq x y
eq _ _ = false
这说明(我希望)是如果 Stateful 的元素具有 Eq 的实例,则它具有 Eq 的实例
有什么方法可以改变它以允许第二个/备份实现?在 SudoCode 伪代码中:
instance statefulEq :: Eq (Stateful a)
where
eq (Advancing (Eq x)) (Advancing (Eq y)) = eq x y
eq (Advancing x) (Advancing y) = true
...
一种说法:如果元素有 Eq 的实例,则使用它,否则返回 true。
或者如果我有一些功能
isConstrained :: forall a. TypeClass -> a -> Boolean
那么也许
instance statefulEq :: Eq (Stateful a)
where
eq (Advancing x) (Advancing y)
| isConstrained Eq x && isConstrained Eq x = eq x y
| otherwise = true
...
解决方法
不,你不能这样做,这是有充分理由的。
你看,约束并不是普遍存在的,它们必须在“范围内”,这基本上意味着从定义它们的模块中导入。
这意味着您的类型的 Eq
约束可以在范围内,也可以不在范围内,您的程序行为将取决于约束是否在范围内。简单来说,添加一个看似无关的模块导入可能会在没有任何警告的情况下改变您的程序行为。
这种“远距离动作”在实践中是一个足够大的错误来源,Haskell 和 PureScript 明确禁止这样做。
另外,附注:您对 Eq (Stateful a)
的实现与自动派生的实现 100% 等效。您可以将整个内容替换为:
derive instance statefulEq :: Eq a => Eq (Stateful a)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。