如何解决模式同义词签名:必需与提供约束
我想我是用 "unusual form" of constraints 理解的。只是检查...
该部分中提供的约束(第二个)的示例似乎都涉及数据构造函数中的 GADT/existentials(?) 对于答案 here,我不确定是否涉及存在 (在 Vinyl 库中),但 rhead
的类型比 f
传递给它的参数具有更具体的类型。并且 PatternSynonym
似乎是一个红鲱鱼: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
对于这样的构造函数,只需忽略约束即可。
上面定义的 pattern ConsSet
与此处的构造函数 DCConsSet
之间是否存在明显的区别:
data (Eq a) => DCSet a = -- constraint on the datatype
DCNilSet
| DCConsSet a (DCSet a)
deriving (Eq,Read)
我的意思是“差异”,而不是一个模式,一个构造函数。我尝试在构建和匹配值中使用它们;我有同样的行为。
解决方法
不,一般来说,必需的约束不会简单地提供与数据类型上下文相同的功能。数据类型上下文引入了一个约束,除了创建数据类型的程序员想要强制该数据类型的用户满足该约束之外,无缘无故地构造或销毁值。它们已被弃用,因为现在认为要求对不需要约束的操作(数据类型构造或销毁)进行约束是不好的做法。相反,应该将约束移近“使用站点”。当以需要约束的方式使用数据类型时,这就是约束应该出现的地方。 (听起来您对这个推理很熟悉。)
相反,如果使用得当,对模式的必需约束引入了构造或销毁值所需的约束,因为该值的构造或销毁使用了提供的实例。 >
例如,给定:
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE PatternSynonyms #-}
pattern Length n <- (length -> n)
Length
的推断类型是:
pattern Length :: Foldable t => Int -> t a
这里,Foldable t
是这里的必需约束,因为在匹配模式时实际上需要它。
正如您所注意到的,您可以滥用具有所需约束的模式来模仿已弃用的数据类型上下文扩展,但是虽然技术上没有使用已弃用的扩展,但您仍在做一些被广泛认为是不好的做法。
至于您的最后一个问题,编译器处理具有上下文的数据类型和具有所需约束的模式的方式相当不同,因此肯定会有差异。一个明显的区别是启用 DataKinds
后,DCNilSet
是一种类型,而 NilSet
不是。
如果您的真正问题是“模式上所需约束的存在是否代表 Haskell 社区承认数据类型上下文实际上是一个不应该被弃用的有价值的特性? ”,我想答案很可能是“不”。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。