如何解决重叠实例

mb1*_*b14 9 haskell

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

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
Run Code Online (Sandbox Code Playgroud)

当然,这些情况在我试图改变的情况下重叠Either a bEither a b,并得到以下错误消息(ParsingError是一个类型别名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
Run Code Online (Sandbox Code Playgroud)

我尝试不同的组合OVERLAPS,OVERLAPPINGOVERLAPPABLE但没有任何工程.我怎么解决这个问题?

use*_*038 10

您将不得不更改其中一个实例定义:

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
Run Code Online (Sandbox Code Playgroud)

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

原始代码的问题在于实例实际上是不连贯的,而不仅仅是重叠,所以没有组合{-# OVERLAPS/OVERLAPPING/OVERLAPPABLE #-}会省去你 - 你需要使用{-# INHCOHERENT #-},这是不可取的,我不建议.GHC将在错误消息中告诉您这种不一致性:

>: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'
Run Code Online (Sandbox Code Playgroud)

本质上,为了从重叠的实例中挑选,一个实例必须对您要匹配的类型"最具体".用户指南中给出了详细信息.

  • 我试着阅读用户指南,但我什么都不懂.你能解释一下`Transformable aa`和'a~b => Transformable ab`之间的区别,以及为什么一个是无条件的,而另一个是好的.它们看起来和我一样. (2认同)
  • 使用'instance {-#OVERLAPPABLE#-} a〜b =&gt; ...`有效。 (2认同)