假设我正在尝试在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)的两个类型类的实例时,我遇到了问题.
从阅读这个问题开始,我现在害怕我所要求的只是被禁止......
为了给出一个特定的解决方案,这样的东西可以工作,而不必处理与(+)的冲突:
class Foo a where
(<+>) :: a -> a -> a
infixl 6 <+>
instance Foo Integer where
(<+>) = (+)
Run Code Online (Sandbox Code Playgroud)
现在你的类Foo有自己的运算符,而fixity声明意味着(<+>)将以与(+)相同的方式解析.
如果您确实要调用操作+,并且要+根据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。
| 归档时间: |
|
| 查看次数: |
529 次 |
| 最近记录: |