Class 为什么Haskell中的实例定义中需要构造函数

Class 为什么Haskell中的实例定义中需要构造函数,class,haskell,instance,Class,Haskell,Instance,有人能解释这个错误吗 实例头中的语法错误(应为构造函数) 谢谢Haskell中有一条规则,约束必须比实例本身“小”。我并不完全理解它背后的理论依据,但作为一个实际问题,您可以使用newtype绕过它 newtype N a = N a instance Num a => Nullable (N a) where default_val = N 0 GHC还可以选择禁用其中一些规则。看 还请注意,您不能将::a放在其中。它在实例声明中没有引用相同的a,但被认为是通用的a,这在那里

有人能解释这个错误吗

实例头中的语法错误(应为构造函数)


谢谢

Haskell中有一条规则,约束必须比实例本身“小”。我并不完全理解它背后的理论依据,但作为一个实际问题,您可以使用
newtype
绕过它

newtype N a = N a

instance Num a => Nullable (N a) where
    default_val = N 0
GHC还可以选择禁用其中一些规则。看


还请注意,您不能将
::a
放在其中。它在实例声明中没有引用相同的
a
,但被认为是通用的
a
,这在那里没有任何意义。

Haskell中有一条规则,约束必须比实例本身“小”。我并不完全理解它背后的理论依据,但作为一个实际问题,您可以使用
newtype
绕过它

newtype N a = N a

instance Num a => Nullable (N a) where
    default_val = N 0
GHC还可以选择禁用其中一些规则。看


还请注意,您不能将
::a
放在其中。它在实例声明中没有引用相同的
a
,但被认为是通用的
a
,这在这里没有任何意义。

讨论

你的代码无效,Haskell。不要误解我的意思——它是Haskell社区中常见的一种形式,可以由GHC编译,但我敦促您不要将“Haskell”与“Haskell加上GHC可以提供的所有扩展”混淆起来

1) 您正在使用另一个typeclass作为约束实例化一个类型类,并且没有任何类型构造函数。在Haskell 2010中,必须具有类型构造函数:

相应实例声明的一般形式为: 实例cx′=>C(tu1…uk)其中{d}其中k≥ 0类型(tu1 …uk)必须采用类型构造函数T的形式应用于简单 类型变量u1,…uk;此外,T不能是类型同义词, 而且ui必须是不同的

GHC在此提供的扩展包括和

2) 您在实例中显式地给出
default\u val
类型。这是完全不必要的,但如果您坚持,那么它也有一个扩展名为

短线

您需要的扩展名可以通过以下方式逐个文件启用:

或者在
ghc
ghci
的命令行上(实际上它只是
ghc
的包装):


同样,许多扩展都是以GHC为中心的。您的代码永远不会在任何其他Haskell编译器上运行,或者我的名字不是John Meacham。

讨论

你的代码无效,Haskell。不要误解我的意思——它是Haskell社区中常见的一种形式,可以由GHC编译,但我敦促您不要将“Haskell”与“Haskell加上GHC可以提供的所有扩展”混淆起来

1) 您正在使用另一个typeclass作为约束实例化一个类型类,并且没有任何类型构造函数。在Haskell 2010中,必须具有类型构造函数:

相应实例声明的一般形式为: 实例cx′=>C(tu1…uk)其中{d}其中k≥ 0类型(tu1 …uk)必须采用类型构造函数T的形式应用于简单 类型变量u1,…uk;此外,T不能是类型同义词, 而且ui必须是不同的

GHC在此提供的扩展包括和

2) 您在实例中显式地给出
default\u val
类型。这是完全不必要的,但如果您坚持,那么它也有一个扩展名为

短线

您需要的扩展名可以通过以下方式逐个文件启用:

或者在
ghc
ghci
的命令行上(实际上它只是
ghc
的包装):

同样,许多扩展都是以GHC为中心的。您的代码永远不会在任何其他Haskell编译器上运行,或者我的名字不是John Meacham。

首先

其次,不要编写表单的实例

instance OtherClass a => Class a where
instance OtherClass a => Class a where
他们不像你想的那样工作。(YMMV使用GHC以外的编译器,但即使在那时我也看不出这是个好主意)。大概您的目的是创建几个实例,例如:

instance Num a => Nullable a where  -- error reported here
  default_val = 0::a

instance Bounded a => Nullable a where
  default_val = minBound
您可以将类型类约束视为函数的额外参数,如下所示:

instance Num a => Nullable a where
  default_val = NumDict a -> 0::a

instance Bounded a => Nullable a where
  default_val = BoundedDict a -> minBound
instance Nullable a where
  default_val = NumDict a -> 0::a

instance Nullable a where
  default_val = BoundedDict a -> minBound
然后ghc实际看到这些类实例如下:

instance Num a => Nullable a where
  default_val = NumDict a -> 0::a

instance Bounded a => Nullable a where
  default_val = BoundedDict a -> minBound
instance Nullable a where
  default_val = NumDict a -> 0::a

instance Nullable a where
  default_val = BoundedDict a -> minBound
现在,编译器应该选择哪个实例?有两个实例都声称对所有类型都有效。所以有一个编译器错误

即使您有一个基于类型类的实例,这也是一个问题。假设您有以下实例:

instance Num a => Nullable a where
  default_val = 0::a

instance Nullable String where
  default_val = ""

instance Nullable BS.ByteString where
  default_val = BS.empty
第一个仍然被认为对所有类型都有效,因此ghc说它需要OverlappingInstances扩展来全部使用它们。这并不完全是邪恶的。但当你试图利用它时,不久ghc将需要另一个扩展,
不连贯性

很多人害怕使用不可判定的实例,但这种担心是错误的。
不可判定实例
可能发生的最坏情况是编译不会终止(但通常会终止)<代码>不连贯
是应该激发恐惧的扩展,因为它会给你的代码带来厄运。如果GHC说您必须启用
不连贯性
,则意味着您需要更改代码

tl;博士

不要编写表单的实例

instance OtherClass a => Class a where
instance OtherClass a => Class a where
他们不会做你想做的事。

首先

其次,不要编写表单的实例

instance OtherClass a => Class a where
instance OtherClass a => Class a where
他们不像你想的那样工作。(YMMV使用GHC以外的编译器,但即使在那时我也看不出这是个好主意)。大概您的目的是创建几个实例,例如:

instance Num a => Nullable a where  -- error reported here
  default_val = 0::a

instance Bounded a => Nullable a where
  default_val = minBound
您可以将类型类约束视为函数的额外参数,如下所示:

instance Num a => Nullable a where
  default_val = NumDict a -> 0::a

instance Bounded a => Nullable a where
  default_val = BoundedDict a -> minBound
instance Nullable a where
  default_val = NumDict a -> 0::a

instance Nullable a where
  default_val = BoundedDict a -> minBound
然后ghc实际看到这些类实例如下:

instance Num a => Nullable a where
  default_val = NumDict a -> 0::a

instance Bounded a => Nullable a where
  default_val = BoundedDict a -> minBound
instance Nullable a where
  default_val = NumDict a -> 0::a

instance Nullable a where
  default_val = BoundedDict a -> minBound
现在,哪一个实例是sho