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.对于任何其他类型类,情况并非如此. 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 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |