haskell - 约束和资金解决方案
问题描述
我有一对 C1 和 C2 类,在 C1 上有一个fundep,如下所示:
class C1 a b | a -> b
class C2 a
我声明一个实例:
instance (C2 a) => C1 a T1
当我声明另一个实例时,我收到一个错误:
instance C1 T2 T3
functional dependencies conflict between instance declarations:
instance C2 a => C1 a T1
instance C1 T2 T3
基本上,我打算将 T1 实例表示为:forall a
where a
is an instance ofC2
b
isT1
,只要T2
不是C2
.
GHC 将其理解为:foralla
b
是T1
,从而排除了将任何其他类型分配给b
.
a
我知道我可以通过包装来解决这个问题newtype
,但这对我的应用程序来说很尴尬。
任何人都可以解释如何获得我想要的行为,如果确实可能的话,或者解释为什么不?
解决方案
您的实例在 FunDep 的“参数”位置重叠。这应该有效(未经测试):
{-# LANGUAGE GADTs, UndecidableInstances #-}
instance {-# OVERLAPPABLE #-} (C2 a, b ~ T1) => C1 a b
instance C1 T2 T3
这是在利用 GHC 的“虚假”FunDep 一致性检查。('bogus' 是 SPJ 编译器代码中的一个注释。)它不应该工作;这非常“作弊”;总有一天有人会修复它,上面的代码将停止工作。
OTOH 自 2008 年以来一直是威胁;它仍然没有得到解决;没有人(除了我)似乎有更好的建议。
以上没有实现的是你的
我的意思是
T1
实例的意思是:is 的实例forall a
在哪里,只要不是 的实例,就允许另一个实例。a
C2 b
T1
T2
C2
但是你知道是否T2
是一个实例C2
——它是一个特定的类型(?)
如果您的意思是任何类型t2
,我认为您需要重新表述这个问题。更高级的重叠和 FunDeps 可能是可行的——而且还有更多的虚假性。
考虑一个辅助类:
{-# LANGUAGE DataKinds #-}
class IsC2 a (t :: Bool) | a -> t
instance IsC2 T2 True
instance (t ~ False) => IsC2 a t
instance IsC2 t2 True
对于每个特定类型t2
,您都需要一个C2
.
instance (IsC2 a t, C1C2 t a T1 T3 b) => C1 a b
class C1C2 t a bt bf b | t bt bf -> b
instance (C2 a) => C1C2 True a bt bf bt -- constraint as belt and braces
instance C1C2 False a bt bf bf
推荐阅读
- windows - 从 Windows 10 PgAdmin 连接安装在 Hyper-V Ubuntu 中的 docker 中的 PostgreSQL
- node.js - 如何使用每封回复的电子邮件将插入记录更新到数据库中?
- excel - 在矩阵中查找所选项目的名称并通过vba显示在列表框中
- postgresql - 如何计算差异和聚合能量作为计数器 - TimescaleDB
- vue.js - Vue从表中更新数据
- go - 如何替换 Go 中的第 n 次出现
- python - 在 RandomForestRegressor 中使用 Partial_fit() 方法
- c# - 如何在 C++ 中调用 C# DLL?
- networking - 如何找出谷歌云 VPN 用于 IKEv1 的密码参数?
- scikit-learn - Sklearn 推荐的无监督学习集群算法