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