【问题标题】:Constraint on method depends on instances in scope?对方法的约束取决于范围内的实例?
【发布时间】:2019-10-19 09:15:28
【问题描述】:

考虑这段代码:

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

x的类型是什么?

λ :type x
x :: C m => m

到目前为止——非常好。现在删除 Int 实例。 x的类型是什么?

λ :type x
x :: Monoid m => m

惊喜!

 

为什么会这样?

【问题讨论】:

    标签: haskell type-inference typeclass


    【解决方案1】:

    以下博客文章中解释了此行为:

    简而言之:GHC 足够聪明,可以看到您只有一个 C 类型类的实例,并确定它是唯一可能的实例,因此每次看到 C m 约束时,它都会将其替换为 Monoid m因为它们是等价的。

     

    注意 就像@chi 在评论中进一步解释的那样:

    当 GHC 发现约束 C t 时,它会尝试解决它。如果找到匹配的instance (...) => C t where ...,则将约束替换为上下文(...)。尽可能地重复这一点。最终约束出现在类型中(或触发“未解决的”类型错误)。这个过程是合理的,因为最多只能有一个匹配的实例。重叠的实例会改变这一点,并在多个实例(在范围内!)大致匹配时防止这种上下文减少。这是一个脆弱的扩展,使用时要小心。

    【讨论】:

    • 我明白了,所以这是一个已知的... 功能?.. 但是,这篇文章并没有解释它的本质。它是类型推断的副作用吗?还是故意的?
    • @IgnatInsarov 不确定它是 功能 还是只是实现细节。但我不是博文作者。因此,通过直接询问 GHC 开发人员,您可能有更好的机会了解这种行为。
    • @IgnatInsarov 当 GHC 找到约束 C t 时,它会尝试解决它。如果找到匹配的instance (...) => C t where ...,则将约束替换为上下文(...)。尽可能地重复这一点。最终约束出现在类型中(或触发“未解决的”类型错误)。这个过程是合理的,因为最多只能有一个匹配的实例。重叠的实例会改变这一点,并在多个实例(在范围内!)大致匹配时防止这种上下文减少。这是一个脆弱的扩展,使用时要小心。
    • 也许@chi 的最后一条评论可以整合到答案中?
    • @chi 我冒昧地整合了您的评论。我觉得我可以接受这样的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-12
    • 1970-01-01
    • 2011-08-22
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    相关资源
    最近更新 更多