为什么不能在Haskell中的实例声明中放置类型签名?

Pra*_*eek 17 haskell instance typeclass type-signature

我喜欢在我的代码中为所有顶级定义添加类型签名.但是,实例声明中的类型签名似乎不被允许,如果我放置一个,我会从GHC获得"错位类型签名"错误.为什么会这样?为什么GHC不能检查类型签名是否与预期相同,如果不是,则拒绝(或警告)?

cro*_*eea 13

您可以使用[new] -XInstanceSigs为实例添加类型签名 ,这对于在范围中引入类型变量特别有用.您可以在官方文档中找到更多信息.


hug*_*omg 12

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

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 = ...
Run Code Online (Sandbox Code Playgroud)


Jon*_*Raa 9

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

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

{-# Language InstanceSigs #-}
Run Code Online (Sandbox Code Playgroud)


Dan*_*her 5

由于签名是类定义的一部分,因此实例声明中的类型签名将是重复的签名。我认为原则上允许重复签名没有问题,但是通常允许重复签名没有任何好处,并且禁止重复签名更简单。因此,语言定义说每个实体最多只能有一个类型签名。在实例声明中也允许签名的功能并没有被要求太多,因此没有扩展允许它。如果确实需要,可以在GHC trac上提出功能请求。如果它引起足够的兴趣,它可能会实现(但我不期望需求很高)。

  • 程序员也会犯错误。:-)例如,程序员可能会错误地认为,要使某些`T`成为`Functor`,必须定义`fmap :: T(a-> b)-> T a-> T b`(感到困惑) (带有“ Applicative”),并编写此类型签名以及一些复杂的fmap实现。当然,“这种类型的签名是错误的,应该是某某某物!” 错误将比将生成的任何“无法使用foo匹配bar,预期的baz,实际的quux”错误更容易理解。 (5认同)
  • 我的意思是检查程序员认为签名是什么(除了检查类中的签名之外)。确实,这没有提供任何额外的安全性。但是它可以给出更易于理解的错误消息:“您认为类型签名是X,但实际上是Y”,而不是其他一些类型错误。而且,它允许程序员采用统一的风格来编写类型声明,而不必在实例声明中进行特殊注释。 (4认同)
  • 我同意这不是一个主要问题,因为没有违反安全性,这更是一个问题,用户与编译器之间的通信更加清晰,并且能够采用统一的编码样式。至于额外的顶层函数,这似乎有点不雅致:它在顶层命名空间中引入了一个不必要的名称(我同意,如果是模块,则无需导出),它将实现与实例声明分开,需要额外的工作和关注,... (3认同)
  • 我们已经在#haskell IRC上谈论了一些。我做了一张票:http://hackage.haskell.org/trac/ghc/ticket/5676 (3认同)
  • @DanBurton太慢了,Prateek数小时前提交了请求:) (2认同)