-- test1.hs
-- :l test1
class StampValue sv
class Particle p where
detect :: (StampValue s) => p -> Int -> s -> Bool
data QValue = R | G | S deriving (Eq)
instance StampValue QValue
data Quantum = Quantum QValue QValue QValue deriving (Eq)
instance Particle Quantum where
detect _ _ S = error "nonsense" -- Почему нельзя испльзовать S?
-- works: detect _ _ _ = True
理论上,在这个例子中,类型QValue是 StampValue 类的一个实例。在函数detect中,我们只有一个限制器(StampValue s) =>。那么为什么我不能使用这种类型的值S作为模式匹配器呢?
另一个有类似问题的例子:
-- test2.hs
-- :l test2
class StampValue sv
class Particle p where
detect :: (StampValue s) => p -> Int -> s -> Bool
type CValue = Bool
instance StampValue Bool -- CValue is an instance of StampValue
data Classical = Classical CValue CValue CValue
instance Particle Classical where
detect (Classical x _ _) _ False = error "Only True" -- Почему нельзя Bool?
-- хотя мы задали, что Bool это инстанция StampValue
-- (без этой строчки компилится нормально)
detect (Classical x _ _) 0 _ = x
detect (Classical _ y _) 1 _ = y
detect (Classical _ _ z) 2 _ = z
detect (Classical _ _ _) _ _ = error "the index is out of range"
尝试编译时的ghci消息:
Couldn't match expected type ‘s’ with actual type ‘Bool’ (или ‘QValue’)
‘s’ is a rigid type variable bound by
the type signature for
detect :: (StampValue s) => Classical -> Int -> s -> Bool
...
虽然看起来:
cmpSpecial :: (Eq e, Num e) => e -> e -> Bool
cmpSpecial _ 0 = False
cmpSpecial 0 _ = False
cmpSpecial x y = (x == y)
它就是这样工作的,虽然它e也不是这里的类型
数字文字不是真正的数据构造函数,与它们的匹配与其他匹配情况不同。
例如
展开成类似的东西(非常示意性地)
因此,
f它必须有一个签名那些。除其他事项外,还需要数字类型实现
Eq,而构造函数匹配则不需要。在您的情况下,函数的主体假定第三个参数的类型是
QValue,并且只有使用它,函数才能工作,尽管根据签名它应该采用更通用的类型。在这种情况下,最简单的方法是使用 GHC 扩展