使用多参数类型类型进行统一

The*_*nce 5 haskell

{-# LANGUAGE MultiParamTypeClasses #-}
class Coerce a b where coerce :: a -> b
instance Coerce a a where coerce a = a
Run Code Online (Sandbox Code Playgroud)

现在,这不起作用:coerce 0 :: Int 但是如果实例被替换为this,则表达式有效:

instance a ~ b => Coerce a b where coerce x = x
Run Code Online (Sandbox Code Playgroud)

为什么?

Ben*_*Ben 10

我可以告诉你为什么第一个不起作用.

Coerce可以为任何可能的类型定义.coerce 0 :: Int被解析为(coerce 0) :: Int.所以你已经用类型注释修复了bin coerce :: a -> b,但不是a.

数字文字是多态的,因此0有类型Num a => a.那不行; 没有实例匹配Coerce a Int.有可能是Coerce Double Int,Coerce Complex Int等,所以明知bInt不足以推断这0是一个Int.我们需要说coerce (0 :: Int) :: Int修复两个类型参数.

相信第二个可行,因为实例声明的约束不用于帮助解析类型类.instance a ~ b => Coerce a b完全匹配就像你写的那样instance Coerce a b.也就是说,这是最常见的实例(出于类型类解析的目的),它可以很好地匹配任何可能的调用coerce(因此你不能写任何其他非重叠的实例).该a ~ b约束仅被施加之后被选择的实例.

由于你有一个匹配任何东西的实例,所以选择一个实例没有问题coerce 0 :: Int,即使我们仍然有同样的问题,不知道它是什么类型0.但是在实例选择之后,我们现在有了额外的约束a ~ Int,它允许将明确的类型分配给所有东西.