您好,在阅读《真实世界》 Haskell书中的示例时,我遇到了这个示例,我无法理解它的含义以及它是如何工作的:
instance Num a=>Num (SymbolicManip a)
在这种情况下,我应该翻译为:“对于类型SymbolicManip
的Num实例,其类型a
的字段存在一个约束,即:a
是一个实例本身”?
有人可以告诉我我是否正确解释或解释?
为什么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-子章-扩展示例-数值类型)
答案 0 :(得分:5)
请务必注意,SymbolicManip a
不能是Num
的实例,而没有a
也是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
请注意,Identity a
可以是Num
的实例,只要a
也是Num
,那么,我们添加一个约束:
instance Num a => Num (Identity a) where
-- (...)
答案 1 :(得分:3)
这意味着,如果a
是Num
的实例,那么SybolicManip a
也是Num
的实例。
所以,如果您有:
x :: SymbolicManip Integer
y :: SymbolicManip Integer
然后,您可以编写x+y
,而无需定义含义。但是,如果相反,您尝试添加两个SymbolicManip String
值,则会出现类型错误,因为String
不是Num
的实例。
如果查看实例,您将看到negate
和fromInteger
都使用Num
的功能。因此,如果您取消约束,则编译器将给出有关无法推断a
是Num
实例的错误。