Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么可以';难道不能在Haskell的实例声明中放置类型签名吗?_Haskell_Instance_Typeclass_Type Signature - Fatal编程技术网

为什么可以';难道不能在Haskell的实例声明中放置类型签名吗?

为什么可以';难道不能在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

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

如果确实需要类型声明,可以在实例体之外单独创建函数

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建议我们做一张票。