为什么 Haskell 的实例定义中需要构造函数
任何人都可以解释这个错误:
实例头中的语法错误(需要构造函数)
class Nullable v where
default_val :: v
instance Num a => Nullable a where -- error reported here
default_val = 0::a
谢谢
Can anyone explain this error:
Syntax error in instance head (constructor expected)
class Nullable v where
default_val :: v
instance Num a => Nullable a where -- error reported here
default_val = 0::a
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
首先,hackage 可以满足您的需求。
其次,不要编写
它们不能按您想要的方式工作的表单实例。 (YMMV 使用 GHC 以外的编译器,但即使如此我也不认为这是一个好主意)。大概您的意图是创建多个实例,例如:
您可以将类型类约束视为函数的额外参数,如下所示:
然后 ghc 实际上会看到这些类实例,如下所示:
现在,编译器应选择哪个实例?有两个实例都声称对所有类型都有效。所以出现了编译器错误。
即使您有一种基于类型类的实例,这也是一个问题。假设您有这些实例:
第一个仍然被认为对所有类型都有效,因此 ghc 表示它需要 OverlappingInstances 扩展才能使用它们。这并不完全是邪恶的。但是当您尝试使用它时,不久之后 ghc 将需要另一个扩展,
IncoherentInstances
。很多人害怕使用 UndecidableInstances,但这种担心是错误的。
UndecidableInstances
可能发生的最糟糕情况是编译不会终止(但通常会终止)。IncoherentInstances
是一个应该会引起恐惧的扩展,因为它会给你的代码带来厄运。如果 GHC 说您必须启用IncoherentInstances
,则意味着您需要更改代码。tl;dr
不要编写以下形式的实例
他们不做你想做的事。
First off, hackage has you covered.
Secondly, don't write instances of the form
they don't work like you want. (YMMV with compilers other than GHC, but I can't see that it's a good idea even then). Presumably your intent is to create several instances, something like:
You can think of type class constraints as an extra argument to a function, like this:
Then ghc actually sees these class instances like this:
Now, which instance should the compiler choose? There are two instances that both claim to be valid for all types. So there's a compiler error.
This is a problem even if you one have one type class based instance. Suppose that you have these instances:
The first is still considered valid for all types, so ghc says that it needs the OverlappingInstances extension to use them all. That's not entirely evil. But when you try to make any use of this, before long ghc will require another extension,
IncoherentInstances
.Lots of people are afraid to use
UndecidableInstances
, but that fear is misplaced. The worst that can happen withUndecidableInstances
is that compiling won't terminate (but it usually does).IncoherentInstances
is the extension which should inspire fear, as it will bring doom upon your code. If GHC says that you have to enableIncoherentInstances
, it means you need to change your code.tl;dr
Don't write instances of the form
They don't do what you want.
Haskell 中有一条规则,约束必须“小于”实例本身。我不太明白它背后的理论依据,但实际上你可以用 newtype 来解决它。
GHC 还可以选择禁用其中一些规则。请参阅http://www.haskell.org/ ghc/docs/latest/html/users_guide/type-class-extensions.html
另请注意,您不能将
::a
放在那里。它在实例声明中并不引用相同的a
,但被视为通用a
,这在那里没有任何意义。There is a rule in Haskell that the constraints must be "smaller" than the instance itself. I don't exactly understand the theoretical justification behind it, but as a practical matter you can get around it with a
newtype
.GHC also has an option to disable some of these rules. See http://www.haskell.org/ghc/docs/latest/html/users_guide/type-class-extensions.html
Also note that you can't put the
::a
in there. It doesn't refer to the samea
in the instance declaration, but is considered a universala
, which wouldn't make any sense there.讨论
您的代码不是有效的 Haskell。不要误会我的意思 - 它是 Haskell 社区中常见的形式,并且可以由 GHC 编译,但我强烈建议您不要将“Haskell”与“Haskell 加上 GHC 可以提供的所有扩展”混淆。
1)您正在使用另一个类型类作为约束来实例化一个类型类,并且没有任何类型构造函数。在 Haskell 2010 中,您必须有一个类型构造函数:
GHC 在这里提供的扩展是 FlexibleInstances 和 UndecidableInstances。
2) 您在实例中明确指定
default_val
类型。这是完全没有必要的,但如果您坚持的话,它也有一个名为 作用域类型变量。简短
您需要的扩展可以使用 语言杂注:
或者在
ghc
或ghci
的命令行(实际上只是一个包装纸ghc
):同样,许多扩展都是以 GHC 为中心的。你的代码永远不会在任何其他著名的 Haskell 编译器上运行,或者我的名字不是 John Meacham。
Discussion
Your code isn't valid Haskell. Don't get me wrong - it's in a form commonly seen in the Haskell community and it can be compiled by GHC, but I urge you not to confuse "Haskell" with "Haskell plus all the extensions GHC can offer".
1) You are instantiating a type class using another typeclass as a constraint and no type constructor what-so-ever. In Haskell 2010 you must have a type constructor:
The extensions GHC offers here are FlexibleInstances and UndecidableInstances.
2) you explicitly give
default_val
a type in your instance. This is entirely unnecessary, but if you insist then this too has an extension called ScopedTypeVariables.The Short
The extensions you need can be enabled either on a file-by-file basis using language pragma:
Or at the command line of either
ghc
orghci
(which actually is just a wrapper aroundghc
):Again, many extensions are GHC-centric. Your code will never run on any other Haskell compiler of note or my name isn't John Meacham.
还有另一种解决方案:此处描述的约束族:
http://dorchard.wordpress.com/2011/09/22/constraint-kinds-in-haskell-finally-bringing-us-constraint-families/
它说它在 GHC 中可用HEAD 或 GHC 7.4(发布后)。
There's also another solution: constraint families described here:
http://dorchard.wordpress.com/2011/09/22/constraint-kinds-in-haskell-finally-bringing-us-constraint-families/
It says it's available in GHC HEAD or GHC 7.4 (when released).