首页 > 解决方案 > 为什么我会收到“约束匹配实例声明”错误?

问题描述

我有以下情况:

instance (Typeable crypto, ToCBOR (SIPHash crypto)) => ToCBOR (SIP crypto) where
  -- ...

instance (Typeable crypto, ToCBOR (Hash crypto SIPData)) =>ToCBOR (SIPHash crypto) where
  -- ...

这会导致以下错误:

• The constraint ‘ToCBOR (SIPHash crypto)’
    matches an instance declaration
  instance (Typeable crypto, ToCBOR (Hash crypto SIPData)) =>
           ToCBOR (SIPHash crypto)
    -- Defined at src/Cardano/Ledger/Spec/STS/Update/Data.hs:383:10
  This makes type inference for inner bindings fragile; 
    either use MonoLocalBinds, or simplify it using the instance 
• In the context: (Typeable crypto, ToCBOR (SIPHash crypto))
  While checking an instance declaration
  In the instance declaration for ‘ToCBOR (SIP crypto)’

为什么我会收到此错误,编译器错误所指的“匹配”是什么?(据我所见,约束是不同的)。

PS:我也尝试在Typeable crypto没有任何运气的情况下删除约束,我猜这是由于编译器没有查看实例声明的 LHS。

标签: haskell

解决方案


从本质上讲,Haskell 是在告诉您,正如所写的那样,这些实例将使您通常认为不可能工作的某些类型推断成为可能。语言扩展改变了类型系统处理这些场景的MonoLocalBinds方式,因此启用它将使您的实例能够按照编写的方式运行,但可能会改变代码的语义。

letHaskell 通常对由or绑定的变量使用最一般(最多态)的解释where,但如果您允许这些类型的实例,可能会有多种不同但同样普遍的解释。MonoLocalBinds将导致解析器使用不太一般的解释,而不是停止或做出任意决定。Vytiniotis 等人有一篇长达 80 页的论文更全面地解释了这个问题,尽管不可否认,我没有时间坐下来阅读它。

正如@chi 指出的那样,GHC 让您知道,您可以完全避免这个问题(在这种情况下),方法是将您的第一个实例替换为:

instance (Typeable crypto, ToCBOR (Hash crypto SIPData)) => ToCBOR (SIP crypto)

推荐阅读