我一直在得到一些奇怪的类型类错误,形式为“没有实例(测试a0)来自表达式类型签名” . 这是我能提出的最简单的违规代码版本:
class Test a where
test :: a
foo = test
添加类型没有帮助:
foo = test :: Test a => a
但是,添加Test实例会使其编译:
instance Test Int where
test = 0
这不是真的可以接受,因为我想在其他地方宣布我的实例 .
最后,将 -XNoMonomorphismRestriction
传递给ghc(i)也允许它编译 . 虽然现在已经足够好了,但我不明白这个扩展的作用是什么,为什么有必要,或潜在的缺点 .
2 回答
作为禁用整个文件的单态限制的替代方法(这是相当无害的,但可能会导致某些意外重新计算不是多态的值),添加类型确实有帮助,但您必须将其作为签名在顶层:
如果在
test
之后添加它,它只被视为子表达式test
上的注释,并且不会关闭foo
本身的单态限制 .阅读this article后,我终于理解了单形态限制 . 关键是看起来像常量的东西不应该是多态的,因为这可能导致它们被多次评估(最坏的情况导致指数减速) .
在我的实际情况中,"constant"本身就是一个函数(通过currying) . 我现在正准备好了;我应该使用
-XNoMonomorphismRestriction
,还是添加类型声明?后者似乎不那么激烈/侵扰,但另一方面,我只是不喜欢MR对我的类型所做的事情 .