首页 > 解决方案 > 类型类实例内的类型类约束

问题描述

你好,在做 Real World Haskell 书中的例子时,我遇到了这个例子,我无法理解它的含义以及它是如何工作的:
instance Num a=>Num (SymbolicManip a)
在这种情况下,我应该翻译成类似:“对于类型的 Num 实例,SymbolicManip有一个关于它的类型字段a,即:a作为 Num 本身的一个实例”?有人可以告诉我我的解释是否正确或解释吗?
为什么还instance Num (SymbolicManip a)不够?

-- The "operators" that we're going to support
data Op = Plus | Minus | Mul | Div | Pow
        deriving (Eq, Show)

{- The core symbolic manipulation type -}
data SymbolicManip a = 
          Number a           -- Simple number, such as 5
        | Arith Op (SymbolicManip a) (SymbolicManip a)
          deriving (Eq, Show)

{- SymbolicManip will be an instance of Num.  Define how the Num
operations are handled over a SymbolicManip.  This will implement things
like (+) for SymbolicManip. -}
instance Num a => Num (SymbolicManip a) where
    a + b = Arith Plus a b
    a - b = Arith Minus a b
    a * b = Arith Mul a b
    negate a = Arith Mul (Number (-1)) a
    abs a = error "abs is unimplemented"
    signum _ = error "signum is unimplemented"
    fromInteger i = Number (fromInteger i)

PS所有代码都来自本书(13章-子-扩展示例-数字类型)

标签: haskelltypeclass

解决方案


重要的是要看到 aSymbolicManip a不能是 So 的实例,也Num不能a是 So 的实例Num,就像我们给函数添加约束一样,我们可以给类型类添加约束:

 instance Num a => Num (SymbolicManip a) where
 --       ^^^^^^^^ "As long as `a` is an instance of `Num`..."
 --                ^^^^^^^^^^^^^^^^^^^^^ "...so is `SymbolicManip a`"

我们必须包含Num a =>约束,因为在实现中,我们使用fromInteger生成类型的成员a。这是不可避免的,就像Num给函数添加约束一样example a b = 2*a + b,即example :: Num a => a -> a -> a

这是一个更简单的例子。考虑这种类型:

newtype Identity a = Identity a

注意 anIdentity a可以是 的实例Num,只要aaNum也是,所以,我们添加一个约束:

instance Num a => Num (Identity a) where
-- (...)

推荐阅读