haskell – 我可以告诉GHC任意选择使用哪个实例,因为我不在乎?

我有一些像这样的代码:

{-# OPTIONS_GHC -Wall #-}
{-# LANUAGE VariousLanguageExtensionsNoneOfWhichWorked #-}

import Control.Applicative
import Data.Either
import Data.Void

class Constructive a where
    lem :: Either (a -> Void) a

instance Constructive Void where
    lem = Left id

instance Num a => Constructive a where
    lem = Right 0

instance Enum a => Constructive a where
    lem = Right $toEnum 0

instance Bounded a => Constructive a where
    lem = Right minBound

instance Monoid a => Constructive a where
    lem = Right mempty

instance Alternative f => Constructive (f a) where
    lem = Right empty

问题是,GHC抱怨

pad.hs:49:10:
    Duplicate instance declarations:
      instance [overlap ok] Bounded a => Constructive a
        -- Defined at pad.hs:49:10
      instance [overlap ok] Monoid a => Constructive a
        -- Defined at pad.hs:52:10

伴随着一堆类似的错误.

有没有办法告诉GHC随机选择一个,因为我不关心它使用的是什么? (我甚至不在乎每次使用lem时它是否选择不同的,因为它没关系.)

最佳答案 这不是你问题的真正答案,更像是一个扩展的评论,暗示了如何解决问题的另一条路线.

在Haskell中,规范的解决方案是为每个实例创建一个newtype,这可能不是你想要的.但是,我想建议你另一种方法.

在Haskell中,我们基本上有3种可能性来构建数据类型:

>使用产品和coproducts(不相交的联合)的代数数据类型.
>功能类型.
>原始类型.

对于第一部分,我们可以使用SYBGHC Generics.如果产品为空,或者具有空因子,则映射到 – >虚空.并且副产品映射到 – >如果它的所有加数都没有效果.

函数类型a – >如果a和b都是:b则是建设性的:

instance (Constructive a, Constructive b) => Constructive (a -> b) where
  ...

如果x :: b是非空的,则a – > b由const x居住.如果a为空,那么a – > b荒谬居住.如果a非空并且b为空,则a – > b映射到Void.

所有Haskell原始类型都是非空的,因此它们非常具有建设性.

不幸的是,似乎没有办法告诉GHC所有数据类型都是这三种中的一种.我的建议是实现 – >的实例.然后要么

>尝试使用SYB为实现Data的所有内容实现实例.如何处理重叠实例仍然存在问题.要么:
>尝试使用GHC Generics为ADT提供默认实例,并为原始类型手动实现实例.这意味着对于每种数据类型,您仍然必须提供空实例实现,默认情况下由Generics提供.

写完这篇文章之后,我发现了AdvancedOverlap.也许将它与之前的方法结合起来可以找到一个很好的解决方案.

点赞