为什么可以';难道不能在Haskell的实例声明中放置类型签名吗?
我喜欢在代码中为所有顶级定义添加类型签名。然而,实例声明中的类型签名似乎是不被允许的,如果我放了一个,我会从GHC得到一个“错位类型签名”错误。为什么会这样?为什么GHC不能检查类型签名是否与预期的相同,如果不相同,则拒绝(或警告)?如果确实需要类型声明,可以在实例体之外单独创建函数为什么可以';难道不能在Haskell的实例声明中放置类型签名吗?,haskell,instance,typeclass,type-signature,Haskell,Instance,Typeclass,Type Signature,我喜欢在代码中为所有顶级定义添加类型签名。然而,实例声明中的类型签名似乎是不被允许的,如果我放了一个,我会从GHC得到一个“错位类型签名”错误。为什么会这样?为什么GHC不能检查类型签名是否与预期的相同,如果不相同,则拒绝(或警告)?如果确实需要类型声明,可以在实例体之外单独创建函数 class Class a where f1 :: a -> a instance Class Foo where f1 = foo_f1 --monomorphic version of
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 = ...
由于签名是类定义的一部分,因此实例声明中的类型签名将是重复签名。我认为原则上允许重复签名是没有问题的,但是一般来说允许重复签名没有好处,而且不允许重复签名更简单。所以语言定义说每个实体最多只能有一个类型签名。允许在实例声明中也使用签名的特性要求不高,因此没有允许它的扩展。如果您真的需要,可以在上提出功能请求。如果它得到足够的关注,它可能会被实现(但我不认为需求会很高)。在任何情况下,类型都是冗余的,人们通常希望避免冗余。
在中,仍然允许为实例成员编写类型签名。它们被检查后扔掉。当然,立即禁止它们更容易。您可以使用[new]为实例添加类型签名,这对于将类型变量引入范围特别有用。您可以在中找到更多信息。这里的大多数其他答案都非常古老。。。现在有一个语言扩展: 将以下内容粘贴在文件顶部:
{-# Language InstanceSigs #-}
我的意思是检查程序员认为签名是什么(除了检查类中的签名)。这并没有给任何额外的安全性,真的。但它可以给出更容易理解的错误消息:“您认为类型签名是X,但实际上是Y”,而不是其他类型的错误。此外,它还允许程序员采用统一的类型声明编写风格,而不必在实例声明中对其进行特殊注释。程序员也可能犯错误。:-)例如,程序员可能会错误地认为,要使某个东西成为某个
T
a函子,必须定义fmap::T(a->b)->ta->tb
(与Applicative
混淆)并编写此类型签名,以及fmap
的一些复杂实现。当然,“这种类型的签名是错误的,应该是某某!”错误比“无法将bar与foo、预期的baz、实际的quux匹配”错误更容易理解。我同意这不是一个大问题,因为没有违反安全性,这更多的是一个用户和编译器之间更清晰的沟通问题,并且能够采用统一的编码风格。至于额外的顶级函数,这似乎有点不雅观:它在顶级名称空间中引入了一个不必要的名称(我同意,如果它是一个模块,就不需要导出),它将实现与实例声明分离,需要额外的工作和注意,……我们在#haskell IRC上已经讨论了一些。我开了一张罚单:@DanBurton太慢了,Prateek在几个小时前提出了一个请求:)在SPJ上评论道:“我自己想要[在实例声明中键入签名],所以我在一个空闲的时间就完成了。”他目前将里程碑设置为GHC 7.6,尽管它进入GHC 7.4的可能性很小。谢谢你问这个问题!谢谢Daniel Fischer建议我们做一张票。