Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.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 为什么这个typeclass只使用“编译”-XnomonomogomismRestriction";?_Haskell_Typeclass - Fatal编程技术网

Haskell 为什么这个typeclass只使用“编译”-XnomonomogomismRestriction";?

Haskell 为什么这个typeclass只使用“编译”-XnomonomogomismRestriction";?,haskell,typeclass,Haskell,Typeclass,我得到了一些奇怪的类型类错误,形式为“表达式类型签名导致的(测试a0)无实例”。下面是我能想到的最简单的违规代码版本: class Test a where test :: a foo = test 添加类型没有帮助: foo = test :: Test a => a 但是,添加一个Test实例会使其编译: instance Test Int where test = 0 这实际上是不可接受的,因为我希望在其他地方声明我的实例 最后,将-XNoMonomorphismRe

我得到了一些奇怪的类型类错误,形式为“表达式类型签名导致的(测试a0)无实例”。下面是我能想到的最简单的违规代码版本:

class Test a where
  test :: a

foo = test
添加类型没有帮助:

foo = test :: Test a => a
但是,添加一个Test实例会使其编译:

instance Test Int where
  test = 0
这实际上是不可接受的,因为我希望在其他地方声明我的实例


最后,将
-XNoMonomorphismRestriction
传递给ghc(i)也允许它进行编译。虽然现在这已经足够好了,但我不明白这个扩展名的作用,为什么它是必需的,或者它可能隐藏着什么缺点。

作为对整个文件禁用单态限制的替代方法(这是相当无害的,但可能会导致一些不打算是多态的值的意外重新计算),添加类型确实有帮助,但您必须将其作为顶级签名:

foo :: Test a => a
foo = test
如果您在
test
之后添加它,它将被视为子表达式
test
上的注释,并且不会关闭
foo
本身的单态限制。

阅读后,我终于理解了单态限制。关键是看起来像常数的东西不应该是多态的,因为这可能会导致它们被多次计算(最坏的情况是导致指数减速)


在我的实际案例中,“常量”本身就是一个函数(通过curry)。我现在在犹豫;我应该求助于
-XNoMonomorphismRestriction
,还是添加类型声明?后者似乎没有那么激烈/打扰,但另一方面,我只是不喜欢MR对我的类型所做的。

我发现这真的很有帮助:啊,好的。我没有意识到这两种类型声明方法是不同的。这是令人困惑的,因为关于单态限制的所有参考资料都建议添加类型声明。无论如何,建议在顶层添加类型声明,因为它既记录了意图,又不让类型推断跨越函数之间的边界,从而减少了类型错误的困惑。“常量”因多态性而有所不同,不是咖喱。尽管禁用MR非常常见,但您还是应该向顶级声明中添加类型签名。@VladFiroiu是的,删除类型签名以了解GHCi认为它们应该是什么当然很方便,但事后再添加类型签名被认为是一个好主意。另外,我强烈推荐新的
-fdefer-type-errors
选项,这样在编程时调整这些东西就不会那么烦人了。我也听到过一些建议,赞成省略类型声明。优点包括使函数尽可能通用,不必写出所有的类型类约束(如果我有很多帮助函数,那就麻烦了),以及使类型级重构的负担更小。@JohnL Right。我想说的是,在我的例子中,MR并没有真正节省很多计算时间,因为函数的计算成本主要取决于应用它的成本。