【问题标题】:Why can't one put type signatures in instance declarations in Haskell?为什么不能将类型签名放在 Haskell 的实例声明中?
【发布时间】:2012-01-12 03:18:00
【问题描述】:

我喜欢将所有顶级定义的类型签名放在我的代码中。但是,实例声明中的类型签名似乎是不允许的,如果我放一个,我会从 GHC 收到“Misplaced type signature”错误。为什么会这样?为什么 GHC 不能检查类型签名是否与预期的相同,如果不是则拒绝(或警告)?

【问题讨论】:

  • the ticket I opened SPJ 评论道:“我自己也想要[实例声明中的类型签名],所以我在空闲时间完成了它。”他目前将里程碑设定为 GHC 7.6,尽管它有可能进入 GHC 7.4。感谢您提出这个问题!感谢 Daniel Fischer 建议我们买票。

标签: haskell instance typeclass type-signature


【解决方案1】:

您可以使用 [新] -XInstanceSigs 为实例添加类型签名,这对于将类型变量引入范围特别有用。您可以在official docs找到更多信息。

【讨论】:

    【解决方案2】:

    如果您真的想要类型声明,您可以在实例主体之外单独创建函数。

    class Class a where
        f1 :: a -> a
    
    instance Class Foo where
        f1 = foo_f1
    
    --monomorphic version of f1 for Foo:
    foo_f1 :: Foo -> Foo
    foo_f1 = ...
    

    【讨论】:

      【解决方案3】:

      这里的大多数其他答案都很老了......现在有一个语言扩展:

      在文件顶部粘贴以下内容:

      {-# Language InstanceSigs #-}
      

      【讨论】:

        【解决方案4】:

        由于签名是类定义的一部分,实例声明中的类型签名将是重复签名。我认为原则上允许重复签名没有问题,但是一般允许重复签名没有任何优势,而且禁止它们更简单。所以语言定义说每个实体最多可以有一个类型签名。在实例声明中也允许签名的功能并没有被要求太多,因此没有允许它的扩展。如果您真的想要,您可以在GHC trac 上提出功能请求。如果它得到足够的兴趣,它可能会被实施(但我预计需求不会很高)。

        【讨论】:

        • 我的意思是检查程序员认为的签名是什么(除了检查类中的签名)。这并没有提供任何额外的安全性,真的。但它可以给出更容易理解的错误信息:“你认为类型签名是 X,但实际上它是 Y”而不是其他一些类型错误。此外,它允许程序员采用统一的编写类型声明的风格,而不必在实例声明中进行特殊情况的注释。
        • 程序员也会犯错。 :-) 例如,程序员可能会错误地认为要制作一些 TFunctor 必须定义 fmap :: T (a -> b) -> T a -> T b(与 Applicative 混淆)并编写此类型签名,以及一些复杂的实现fmap。肯定是“这种类型的签名是错误的,应该是某某!”错误将比将生成的“无法将 bar 与 foo、预期的 baz、实际的 quux 匹配”错误更容易理解。
        • 我同意这不是一个大问题,因为没有违反安全性,更多的是用户和编译器之间更清晰的沟通以及能够采用统一的编码风格的问题。至于额外的顶级函数,这似乎有点不雅:它在顶级命名空间中引入了一个不必要的名称(如果它是一个模块,则不需要导出,我同意),它将实现与实例声明分开,它需要额外的工作和关注,...
        • 我们已经在#haskell IRC 上讨论了这个问题。我订了票:hackage.haskell.org/trac/ghc/ticket/5676
        • @DanBurton 太慢了,Prateek 几小时前提交了请求 :)
        【解决方案5】:

        在任何情况下,类型都是冗余的,通常希望避免冗余。 在Frege 中,仍然允许为实例成员编写类型签名。他们被检查然后扔掉。立即禁止它们当然更容易。

        【讨论】:

          猜你喜欢
          • 2013-12-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-09
          • 2011-09-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多