概括加法时的GHC重叠实例 [英] GHC Overlapping instances when generalising addition

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

问题描述

试图将(+)推广到不仅仅是Num的地方,我写了一个Addable类:

Trying to generalise (+) to more than just Nums, I wrote a up an Addable class:

{-# LANGUAGE FlexibleContexts, FlexibleInstances, UndecidableInstances #-}

class Addable a where
  (+) :: Addable a => a -> a -> a

instance Addable [a] where
  (+) = (++)

instance Num a => Addable a where
  (+) = (Prelude.+)

当尝试添加(连接)列表时,GHC抱怨实例重叠:

When trying to add (concatenate) lists, GHC complains about overlapping instances:

*Test> "abc" + "defghi"

<interactive>:84:7:
    Overlapping instances for Addable [Char] arising from a use of `+'
    Matching instances:
      instance Num a => Addable a -- Defined at Utils.hs:23:10
      instance Addable [a] -- Defined at Utils.hs:20:10
    In the expression: "abc" + "defghi"
    In an equation for `it': it = "abc" + "defghi"

我知道GHC在选择类型类的实例时会忽略上下文,因此尝试在Addable [a]Addable a之间进行选择确实是一个问题.但是,我希望GHC选择第一个定义,因为它更具体. 为什么不发生这种情况?

I know that GHC disregards context when choosing instances of typeclasses, so trying to choose between Addable [a] and Addable a is indeed a problem. However, I expect GHC to choose the first definition since it is more specific. Why isn't that happening?

此外,是否存在解决此问题的简便方法?还是我从错误的角度出发?

Furthermore, is there an elegant workaround for this problem? Or am I going at this from the wrong angle?

推荐答案

您需要启用重叠的实例才能真正使用.在较早版本的编译器中,您可以使用OverlappingInstances扩展名按模块进行此操作:

You need to enable overlapping instances in order to actually use them. In older versions of the compiler, you could do this per-module with the OverlappingInstances extension:

{-# LANGUAGE OverlappingInstances #-}

此代码适用于此代码

λ> :set -XOverlappingInstances
λ> "abc" + "def"
"abcdef"

但是,GHC的较新版本(至少在8.0中)不赞成使用此方法:

However, this approach is deprecated in newer versions of GHC (at least in 8.0):

Misc.hs:1:73-92: warning: …
    -XOverlappingInstances is deprecated: 
      instead use per-instance pragmas OVERLAPPING/OVERLAPPABLE/OVERLAPS

因此,更现代的方法是根据每个实例进行指定:

So the more modern approach is to specify this on a per-instance basis:

instance {-# OVERLAPPABLE #-} Num a => Addable a where
  (+) = (Prelude.+)

OVERLAPPINGOVERLAPSINCOHERENT也存在这种杂用样式,可让您使用这些属性注释特定的实例.

This style of pragma also exists for OVERLAPPING, OVERLAPS and INCOHERENT, letting you annotate specific instances with these properties.

这篇关于概括加法时的GHC重叠实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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