Haskell 当类型是自由变量时,实例内类型签名中的类型类约束

Haskell 当类型是自由变量时,实例内类型签名中的类型类约束,haskell,Haskell,当类型是Haskell中的自由变量时,如何在实例内的类型签名中添加类型类约束。例如: {-# LANGUAGE InstanceSigs #-} class Pair a where pair :: a -> b -> (a, b) instance Pair Int where pair :: (Show a) => a -> b -> (a, b) pair a b = (a, b) “a”是一个绑定类型变量,而: {-# LANG

当类型是Haskell中的自由变量时,如何在实例内的类型签名中添加类型类约束。例如:

{-# LANGUAGE InstanceSigs #-}

class Pair a where
    pair :: a -> b -> (a, b)

instance Pair Int where
    pair :: (Show a) => a -> b -> (a, b)
    pair a b = (a, b)
“a”是一个绑定类型变量,而:

{-# LANGUAGE InstanceSigs #-}

class Pair a where
    pair :: a -> b -> (a, b)

instance Pair Int where
    pair :: (Show b) => a -> b -> (a, b)
    pair a b = (a, b)
给出此错误:

source_file.hs:8:13:
    No instance for (Show b)
    Possible fix:
      add (Show b) to the context of
        the type signature for pair :: Int -> b -> (Int, b)
    When checking that: forall a b. Show b => a -> b -> (a, b)
      is more polymorphic than: forall b. Int -> b -> (Int, b)
    When checking that instance signature for ‘pair’
      is more general than its signature in the class
      Instance sig: forall a b. Show b => a -> b -> (a, b)
         Class sig: forall b. Int -> b -> (Int, b)
    In the instance declaration for ‘Pair Int’
你不能

对的类型
对于所有a b都是
。对a=>a->b->(a,b)

其中
a=Int
,专门用于所有b的
。Int->b->(Int,b)

在第一个示例中,您对所有AB的类型声明
。显示a=>a->b->(a,b)
专门用于所有b的
。Show Int=>Int->b->(Int,b)
,然后进一步减少到所有b的
。Int->b->(Int,b)
。(Show约束被删除,因为它是多余的;您正在“约束”一个具体的类型,这是没有意义的。)这是正确的类型


在第二个示例中,您试图定义一个实例,其中
pair
的类型为
forall b。Show b=>Int->b->(Int,b)
,这不起作用,因为这是另一种类型。

在概念直观的层面上,
类对是对消费者的承诺。它说“有一个函数
,它将适用于这种类型的
a
和任何其他类型的
b
”。任何看到该类的人都可以使用任何类型的函数
b


但您的实例试图说“我将实现此函数
pair
,但仅适用于具有
Show
实例的
b
s”。好吧,这不是类的完整实现:类承诺为任何
b
工作,但实例只对某些
b
工作。

我认为这是不可能的。您基本上是在尝试更改show函数的类型签名。在第一个示例中,a上的Show约束用作实例的约束,在第二个示例中,pairs类型被更改为
Show b=>a->b->(a,b)
在第一种情况下,它统一了类型
(Show x)=>x->b->(x,b)
Int->b->(Int,b)
,它们在
x~Int
时统一。在这种情况下,
Show x
约束是完全冗余的,这就是为什么它被允许存在的原因——当类型被简化时,它会被删除。您没有在任何意义上“添加”任何约束。在第二种情况下,类型
showb=>x->b->(x,b)
Int->b->(Int,b)
根本不统一;像以前一样设置
x~Int
仍然会留下不匹配的
Show b
约束(这正是编译器告诉您的)。我在这里无意中寻找将约束添加到实例声明中的语法,就像这样
instance SomeOtherClass a=>classbeingimplementa where