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

时间:2017-11-14 22:36:57

标签: haskell

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

DoIt

有效,' a'是一个绑定类型变量,而:

{-# 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)

给出了这个错误:

{-# 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)

2 个答案:

答案 0 :(得分:4)

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

但是您的实例试图说“我将实现此功能pair,但仅适用于具有b实例”的Show。好吧,这不是一个完整的类实现:该类承诺适用于任何b,但该实例仅适用于某些 b

答案 1 :(得分:3)

你不能。

pair的类型为forall a b. Pair a => a -> b -> (a, b)

a = Int的位置,这适用于forall b. Int -> b -> (Int, b)

在第一个示例中,您的类型声明forall a b. Show a => a -> b -> (a, b)专门针对forall b. Show Int => Int -> b -> (Int, b),然后进一步缩减为forall b. Int -> b -> (Int, b)。 (Show约束只是被删除,因为它是多余的;你是"约束"具体类型,这是没有意义的。)这是正确的类型。

在第二个示例中,您尝试定义一个pair类型为forall b. Show b => Int -> b -> (Int, b)的实例,但由于该类型不同,因此无效。<\ n / p>