haskell – 将任意类约束“C a”转换为“C a Bool”

前端之家收集整理的这篇文章主要介绍了haskell – 将任意类约束“C a”转换为“C a Bool”前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
所以在C中有一个Bool形式的类型有很多优点.主要是因为它们允许您在两个约束之间进行任何逻辑运算,当正常的C只是隐含地将所有内容进行AND.

如果我们考虑〜类约束,可以这样做

class Equal x y b | x y -> b
instance Equal x x True
instance False ~ b => Equal x y b

但是,这种情况特别的是将x x放在实例的头部相当于x〜y =>然后在头上x y.对于任何其他类型类,情况并非如此.
所以如果我们尝试为类C做类似的事情,我们会得到类似的东西

class C' x b | x -> b
instance C x => C' x True
instance False ~ Bool => C' x b

不幸的是,这不起作用,因为这些实例中只有一个将被挑选,因为它们不区分类型x,所以任何类型都匹配两个头.

我也读过https://www.haskell.org/haskellwiki/GHC/AdvancedOverlap,这再一次不适用于任何C类,因为它需要你重写所有的原始类的实例.理想情况下,我希望我的代码与GHC.Exts.Constraint和KindSignatures一起使用,以便C可以参数化.

所以,这样一个类

class Match (c :: * -> Constraint) x b | c x -> b

如果且仅当c x,Match c x False时,如何编写实例才能使Match c x True?

解决方法

由于所谓的开放世界假设,这在哈斯克尔是不可能的.它指出,类型类的实例集是打开的,这意味着您可以随时创建新的实例(而不是封闭的世界,其中必须有一组固定的实例).例如,虽然Funlude类型在Prelude中定义,但我仍然可以在我自己的代码中为Prelude创建实例.

为了实现你的建议,编译器需要一种方法来检查类型T是否是类C的实例.然而,这需要编译器知道该类的所有可能的实例,这是不可能的,因为的开放世界假设(在编译Prelude时,编译器还不知道你以后使YourOwnFunctor成为Functor的一个实例).

使其工作的唯一方法是仅考虑当前可见的实例(因为它们在当前模块中定义或其任何导入).但是这将导致相当不可预测的行为:可见实例集不仅取决于模块的导入,还取决于导入导入,因为您无法隐藏实例.因此,您的代码的行为将取决于您的依赖关系的实现细节.

如果你想要一个封闭的世界,你可以使用closed type families,这是在GHC 7.8中引入的.使用它们,你可以写:

type family Equal a b :: Bool where
  Equal x x = True
  Equal x y = False
原文链接:https://www.f2er.com/c/113055.html

猜你在找的C&C++相关文章