我想我是通过约束的“不寻常形式”来理解它的。只是检查 ...
该部分中提供的约束(第二个)的示例似乎都涉及数据构造函数中的 GADT/existentials(?)有了这里的答案,我不确定是否涉及存在(在 Vinyl 库中),但是for的类型比传递给它rhead
的参数具有更具体的类型。f
并且 tbhPatternSynonym
似乎是一条红鲱鱼:OnlyRecord
不出现在f
rhs 上的论点。
所需的约束(两个中的第一个,或者如果有一个,则只有一个)似乎提供与现在已弃用的相同功能DatatypeContexts
(?)
data NoCSet a where -- no constraints on the datatype
NilSet_ :: NoCSet a
ConsSet_ :: a -> NoCSet a -> NoCSet a
deriving (Eq, Show, Read)
pattern ConsSet :: (Eq a) => () => a -> NoCSet a -> NoCSet a
-- Req'd => Prov'd => type; Prov'd is empty, so omittable
pattern ConsSet x xs = ConsSet_ x xs
pattern NilSet :: (Eq a) => () => NoCSet a
pattern NilSet = NilSet_
ccUnit = ConsSet () NilSet -- accepted
-- ccid = ConsSet id NilSet -- rejected no instance Eq (a -> a)
-- ncid = NilSet :: NoCSet (a -> a) -- ditto
有了额外的优势,我可以在NilSet
没有参数的情况下对模式设置必需的约束,甚至不允许构建具有不可接受类型的空集。DatatypeContexts
对于这样的构造函数,只需忽略约束。
编辑/重点问题:(回复@Noughtmare 评论)
pattern ConsSet
上面定义的和这里的构造函数之间是否有明显的区别DCConsSet
:
data (Eq a) => DCSet a = -- constraint on the datatype
DCNilSet
| DCConsSet a (DCSet a)
deriving (Eq, Show, Read)
我的意思是“差异”,而不是一个模式,一个是构造函数。我已经尝试在构建和匹配值中使用它们;我得到同样的行为。