编译器不会选择多态常量值的类型类 [英] Compiler doesn't pick up typeclass for the polymorphic constant value
问题描述
我是Haskell的新手,所以请原谅我.
I'm new to Haskell, so forgive me in advance.
为什么以下haskell代码无法编译?
Why doesn't the following haskell code compile?
似乎编译器以某种方式未能看到表达式(maxBound :: a)
的类型是 a
且具有 Enum
提供的实例,而不是一些歧义
的类型变量'a0'
.
It seems like the compiler somehow fails to see that the type of the expression (maxBound :: a)
is a
which has an Enum
instance provided, not some type variable ‘a0’
which is ambiguous
.
class (Enum a, Bounded a) => SafeEnum a where
ssucc :: a -> a
ssucc x = if (fromEnum x) < (fromEnum (maxBound :: a)) then succ x else minBound
spred :: a -> a
spred x = if (fromEnum x) > (fromEnum (minBound :: a)) then pred x else maxBound
Stepik.hs:3:32: error:
• Could not deduce (Enum a0) arising from a use of ‘fromEnum’
from the context: SafeEnum a
bound by the class declaration for ‘SafeEnum’
at Stepik.hs:(1,1)-(6,82)
The type variable ‘a0’ is ambiguous
These potential instances exist:
instance Enum Ordering -- Defined in ‘GHC.Enum’
instance Enum Integer -- Defined in ‘GHC.Enum’
instance Enum () -- Defined in ‘GHC.Enum’
...plus six others
推荐答案
默认情况下,即使类型变量的范围从定义的类到类方法的类型签名(即 a
SafeEnum a 类中的>与 ssucc :: a-> a
中 a
中的 a
相同,它们不在范围内,从方法的类型签名到方法主体,因此在函数主体中的表达式 maxBound :: a
中 ssucc
和 spred
, a
与这些功能的类型签名中的 a
没有关系.
By default, even though type variables are scoped from the class being defined to the type signatures of the class's methods (i.e., the a
in class SafeEnum a
is the same a
as the a
in ssucc :: a -> a
), they are not scoped from the type signatures of the methods to the method bodies, so in the expression maxBound :: a
in the bodies of your functions ssucc
and spred
, the a
has nothing to do with the a
in the type signatures for those functions.
您可以启用 ScopedTypeVariables
扩展名,如下所示:
You can enable the ScopedTypeVariables
extension, like so:
{-# LANGUAGE ScopedTypeVariables #-}
之后,类定义将键入check.
after which the class definition will type check.
请注意,如果您使用 forall
关键字,则此扩展名仅适用于常规"函数声明.因此,在类定义之外,您需要启用此扩展 并写:
Note that this extension only applies to "normal" function declarations if you use the forall
keyword. So, outside of a class definition, you'd need to enable this extension and write:
ssucc :: forall a. a -> a
ssucc x = ... maxBound :: a ...
或实际上:
ssucc :: forall a. (Enum a, Bounded a) => a -> a
ssucc x = ... maxBound :: a ...
,但是 class
子句中的规则不同.
but the rules are different inside a class
clause.
请参见 GHC文档了解详情.
这篇关于编译器不会选择多态常量值的类型类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!