繁体   English   中英

类型类实例中的类型类约束

[英]Typeclass constraint inside typeclass instance

你好,从Real World Haskell书中做例子,我遇到过这个例子,我无法理解它的含义以及它是如何工作的:
instance Num a=>Num (SymbolicManip a)
在这种情况下,我应该转换为类似于:“对于类型为SymbolicManip Num实例,对于其类型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 - 子章节 - 扩展示例 - 数值类型)

地看到,这是重要的SymbolicManip a不能被实例Numa也作为一个实例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成员。 这是不可避免的 ,就像向函数example ab = 2*a + b添加Num约束,即example :: Num a => a -> a -> a

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

newtype Identity a = Identity a

请注意, Identity a可以是Num的实例,只要a也是Num ,因此,我们添加一个约束:

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

这意味着如果aNum的实例,则SybolicManip a也是Num的实例。

所以如果你有:

x :: SymbolicManip Integer
y :: SymbolicManip Integer

然后你可以编写x+y而无需定义它的含义。 但是,如果您尝试添加两个SymbolicManip String值,则会出现类型错误,因为String不是Num的实例。

如果查看实例,您将看到negatefromInteger都使用Num功能。 因此,如果您取出约束,那么编译器会给出关于无法推断出aNum实例的错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM