首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >显示的重叠实例

显示的重叠实例
EN

Stack Overflow用户
提问于 2019-05-02 07:41:13
回答 2查看 527关注 0票数 0

假设我们有以下内容:

代码语言:javascript
复制
{-# LANGUAGE FlexibleInstances #-}

module Sample where

newtype A a =
  A a
  deriving (Show)

newtype L a =
  L [a]

class ListContainer l where
  getList :: l a -> [a]

instance ListContainer L where
  getList (L l) = l

instance (Show a, ListContainer l) => Show (l a) where
  show = const "example"

使用此代码,ghc抱怨:

代码语言:javascript
复制
warning: [-Wdeferred-type-errors]
• Overlapping instances for Show (A a)
    arising from a use of ‘GHC.Show.$dmshowList’
  Matching instances:
    instance (Show a, ListContainer l) => Show (l a)
      -- Defined at /.../src/Sample.hs:18:10
    instance Show a => Show (A a)
      -- Defined at /.../src/Sample.hs:7:13
• In the expression: GHC.Show.$dmshowList @(A a)
  In an equation for ‘showList’:
      showList = GHC.Show.$dmshowList @(A a)
  When typechecking the code for ‘showList’
    in a derived instance for ‘Show (A a)’:
    To see the code I am typechecking, use -ddump-deriv
  In the instance declaration for ‘Show (A a)’
warning: [-Wdeferred-type-errors]
• Overlapping instances for Show (A a)
    arising from a use of ‘GHC.Show.$dmshow’
  Matching instances:
    instance (Show a, ListContainer l) => Show (l a)
      -- Defined at /.../src/Sample.hs:18:10
    instance Show a => Show (A a)
      -- Defined at /.../src/Sample.hs:7:13
• In the expression: GHC.Show.$dmshow @(A a)
  In an equation for ‘show’: show = GHC.Show.$dmshow @(A a)
  When typechecking the code for ‘show’
    in a derived instance for ‘Show (A a)’:
    To see the code I am typechecking, use -ddump-deriv
  In the instance declaration for ‘Show (A a)’

我可以理解,它认为a类型可以派生Show,也可以派生ListContainer,这可能导致Show

我们怎么才能避免呢?

我知道有一个函数showList,但是它的签名有点陌生。我已经有了一个函数,用于显示某些列表,它直接返回String

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-05-02 12:16:44

我能理解的是,它认为a类型可以是派生Show,也可以是派生ListContainer,这可能会导致Show

这不是它所想的。

当Haskell选择类实例时,它根本不考虑实例约束。在选择实例时,它只考虑实例头(类名后面的内容)。

在您的Show实例中,实例头是l a。此实例头与A a匹配(假设为l = A)。顺便说一句,它还匹配了许多其他东西--例如,它匹配Maybe a (其中l = Maybe)、Either b a (与l = Either b)、Identity aIO a --想想看,几乎每种类型都有一个类型参数。AMaybeIO都没有ListContainer的实例,这并不重要,因为正如我前面所说的,Haskell在选择实例时不考虑约束,只是在实例头上。

只有在找到匹配实例(通过头上的匹配)之后,Haskell才会检查该实例的约束实际上是否得到满足。如果他们不这样做的话,他们会抱怨,但它永远不会回去,转而选择另一个例子。

所以回到您的示例:因为A现在有两个匹配的Show实例--它自己的派生实例和您编写的Show (l a)实例,编译器抱怨它们是重叠的。

票数 4
EN

Stack Overflow用户

发布于 2019-05-02 08:18:32

在您的示例中,只需删除instance (Show a, ListContainer l) => Show (l a)并将deriving (Show)添加到L定义中即可。

或者,您可以从deriving (Show)定义中删除A

如果您希望代码按照现在的样子运行,请删除deriving (Show)并显式地实现它。

代码语言:javascript
复制
 instance {-# OVERLAPPING #-}  Show a => Show (A a)
      where 
         show (A a) = "A " ++ show a
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55947743

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档