簡體   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