Haskell如何在实例声明期间推断类型?

时间:2018-09-09 03:00:01

标签: haskell

我有这种数据类型和实例声明:

class Expr a where
  lit :: Integer -> a

data Mod7 = Mod7 Integer deriving (Eq, Show)

instance Expr Mod7 where
  lit x = Mod7 (x `mod` 7)

这样编译就可以了。我认为那是因为这一行

lit x = Mod7 (x `mod` 7)

推断x是可以传递给mod的类型。没有一些明确的声明怎么会发生这种推断?

mod的定义是

mod :: Integral a => a -> a -> a

因此,根据以上声明,完全有可能lit被传递了没有声明函数的Integral类型。 GHC如何知道要分配给x的类型?

1 个答案:

答案 0 :(得分:8)

实例声明中的

类型推断与任何其他上下文相同。在这种情况下,有两行推理证明xInteger

  1. x出现在表达式Mod7 (x `mod` 7)中。由于Mod7构造函数声明为接受Integer自变量,因此x `mod` 7必须是Integer。由于mod的类型为Integral a => a -> a -> a,因此如果x `mod` 7的结果为Integer,则x7都必须为{{ 1}}(这仅在Integer成立的情况下有效,但可以这样做)。

  2. Integral Integer已声明为类型lit(在Expr a => Integer -> a的类定义中)。 Expr a被绑定为x定义中的参数,因此它的类型必须为lit

特定于实例声明的唯一事情是类型检查器可以使用此特定实例的类型实例化在类中声明的函数的类型。因此,它实际上知道(因为在Integer中,instance Expr Mod7的定义是针对lit的。但是,甚至不需要建立lit :: Integer -> Mod7,因为自变量x :: Integer的类型在lit的每个实例中都是相同的(此特定于实例的知识用于确定调用Expr构造函数是构建返回值的正确方法,但不是与推断Mod7的类型无关。