如何解决重叠的实例 [英] How to resolve overlapping instance

查看:61
本文介绍了如何解决重叠的实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码(转换类似于转换)

I have the following code (transform is similar to convert)

instance {-# OVERLAPS #-} Transformable a a where
  transform x = x

instance {-# OVERLAPPABLE #-} (Transformable l l',   Transformable r r' )
         => Transformable (Either l r) (Either l' r')
  where
    transform = bimap transform transform

当然,在我尝试将 Ab 转换为 Ab 并获得以下错误消息( ParsingError 其他任何东西)

Of course, those instances overlap in the case where I'm trying to transform Either a b to Either a b and get the following error message (ParsingError is a type alias for Either something somethingElse)

    Overlapping instances for Transformable
                                (parsingerror text) (parsingerror text)
      arising from a use of ‘makereceipt’
    matching instances:
Matching instances:    Overlapping instances for Transformable
                            (ParsingError Text) (ParsingError Text)
  arising from a use of ‘makeReceipt’
Matching instances:
  instance [overlappable] (Transformable l l', Transformable r r') =>
                          Transformable (Either l r) (Either l' r')
      instance [overlappable] (Transformable l l', Transformable r r') =>
                              Transformable (Either l r) (Either l' r')
        -- Defined at Handler/GLEnterReceiptSheet/ReceiptRow.hs:154:31
      instance [overlap ok] Transformable a a
        -- Defined at Handler/GLEnterReceiptSheet/ReceiptRow.hs:151:27

我尝试了 OVERLAPS OVERLAPPING OVERLAPPABLE 的不同组合,但是没有任何效果.我该如何解决?

I tried different combination of OVERLAPS, OVERLAPPING and OVERLAPPABLE but nothing works. How can I solve this ?

推荐答案

您将不得不更改实例定义之一:

You will have to change one of the instance definitions:

class Transformable a b where 
  transform :: a -> b 

-- this one
instance {-# OVERLAPS #-} (a ~ b) => Transformable a b where
  transform x = x

instance (Transformable l l', Transformable r r' )
       => Transformable (Either l r) (Either l' r') where
  transform = either (Left . transform) (Right . transform) 

test0 :: (Transformable a a', Transformable b b') => Either a b -> Either a' b'
test0 = transform

并且该代码将起作用,无论您在另一个实例上使用哪个重叠.在第二个实例上,您实际上不需要任何编译指示.

And the code will work regardless of which overlap you use on the other instance. You don't actually need any pragma on the second instance.

原始代码的问题在于实例实际上是不连贯的,而不仅仅是重叠的,因此 {-#OVERLAPS/OVERLAPPING/OVERLAPPABLE#-} 的组合没有这样可以节省您的钱-您需要使用 {-#INCOHERENT#-} ,这是不理想的,我也不建议这样做.GHC会通过错误消息告诉您这种不一致的情况:

The problem with the original code is that the instances are actually incoherent, not just overlapping, so no combination of {-# OVERLAPS / OVERLAPPING / OVERLAPPABLE #-} would save you - you would need to use {-# INCOHERENT #-}, which is not desirable and I wouldn't recommend it. GHC will tell you about this incoherence with the error message:

>:t transform :: (Transformable a a', Transformable b b') => Either a b -> Either a' b'

<interactive>:1:1: Warning:
    Overlapping instances for Transformable
                                (Either a1 b1) (Either a'1 b'1)
      arising from a use of `transform'
    Matching instances:
      instance [overlappable] (Transformable l l', Transformable r r') =>
                              Transformable (Either l r) (Either l' r')
        -- Defined at test6.hs:9:31
      instance [overlap ok] Transformable a a -- Defined at test6.hs:6:27
    (The choice depends on the instantiation of `a1, b1, a'1, b'1'
     To pick the first instance above, use IncoherentInstances
     when compiling the other instance declarations)
    In the expression:
        transform ::
          (Transformable a a', Transformable b b') =>
          Either a b -> Either a' b'

本质上,为了从重叠的实例中进行选择,一个实例必须是最具体的"实例.针对您要匹配的类型.有关详细信息,请参见用户指南.

Essentially, in order to pick from overlapping instances, one instance must be "most specific" for the type(s) you are trying to match. The details of this are given in the user guide.

这篇关于如何解决重叠的实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆