Ign*_*rov 6 haskell type-inference typeclass
考虑以下代码:
{-# language FlexibleInstances, UndecidableInstances #-}
module Y where
class C m where
x :: m
instance {-# overlappable #-} Monoid m => C m where
x = mempty
instance C Int where
x = 53
Run Code Online (Sandbox Code Playgroud)
什么是x?
? :type x
x :: C m => m
Run Code Online (Sandbox Code Playgroud)
到目前为止,一切都很好。现在删除Int实例。什么是x?
? :type x
x :: Monoid m => m
Run Code Online (Sandbox Code Playgroud)
惊喜!
为什么会这样呢?
以下博客文章中对此行为进行了解释:
简而言之:GHC足够聪明,可以看到您只有一个C类型类的实例,并确定它是唯一可能的实例,因此每次看到C m约束时,它都会被替换,Monoid m因为它们是等效的。
NB As @chi在评论中进一步解释:
当GHC找到约束时C t,它将尝试解决它。如果找到匹配项instance (...) => C t where ...,则将约束替换为上下文(...)。尽可能重复此过程。最终约束出现在类型中(或触发“未解决的”类型错误)。该过程是合理的,因为最多只能有一个匹配的实例。重叠的实例会更改此设置,并在多个实例(在范围内)大致匹配时防止这种上下文减少。这是一个易碎的扩展,需要谨慎使用。