使基本Haskell类型成为新类型类的实例

Pie*_*rre 8 haskell

假设我正在尝试在Haskell中定义一个新的类型类,除此之外,它必须有一个+操作:

class Foo a where
    (+) :: a -> a -> a
Run Code Online (Sandbox Code Playgroud)

(在实践中,类型类Foo会有更多的东西,但让我在这里停下来保持这个最小.)

现在,我想让基本的"整数"类型成为Foo的一个实例; 就+操作而言,我只想保留已经定义的常规添加.我怎么做?

毋庸置疑,以下内容毫无意义:

instance Foo Integer where
    (+) x y = x+y
Run Code Online (Sandbox Code Playgroud)

当我要求Haskell计算2 + 3时,它会永远循环,但我想这是预期的!我也试过什么都不做:

instance Foo Integer
Run Code Online (Sandbox Code Playgroud)

这个编译,但是当我要求2 + 3时,我得到"没有实例也没有类操作的默认方法+".再次,它是有道理的......

但那我们怎么做呢?

我想这是关于命名空间的一般性问题,我的意思是,当两个类型使用相同的名称时,会发生什么?在我的例子中,当我尝试使用这样的名称冲突(Num和Foo)创建一个类型(Integer)的两个类型类的实例时,我遇到了问题.

从阅读这个问题开始,我现在害怕我所要求的只是被禁止......

Sam*_*arr 9

为了给出一个特定的解决方案,这样的东西可以工作,而不必处理与(+)的冲突:

class Foo a where
  (<+>) :: a -> a -> a

infixl 6 <+>

instance Foo Integer where
  (<+>) = (+)
Run Code Online (Sandbox Code Playgroud)

现在你的类Foo有自己的运算符,而fixity声明意味着(<+>)将以与(+)相同的方式解析.


Tan*_*ett 5

如果您确实要调用操作+,并且要+根据Prelude中的定义进行操作,则可以这样操作:

import Prelude (Integer, print)
import qualified Prelude ((+))

class Foo a where
  (+) :: a -> a -> a

instance Foo Integer where
  (+) x y = x Prelude.+ y

main = print (2 + 3 :: Integer)
Run Code Online (Sandbox Code Playgroud)

这将输出5。

为了证明的定义main确实在使用我们的新+运算符而不是原始运算符,我们可以更改以下定义+

import Prelude (Integer, print)
import qualified Prelude ((+))

class Foo a where
  (+) :: a -> a -> a

instance Foo Integer where
  (+) x y = x Prelude.+ y Prelude.+ 1

main = print (2 + 3 :: Integer)
Run Code Online (Sandbox Code Playgroud)

这将输出6。