Haskell代码无法编译:“非法的数据类型上下文”

29

我无法在Haskell中编译这行代码,但它在我的教授的系统上有效。 我使用的是ghci版本7.6.2。

data Eq a => Shape a = Shape a

更准确地说,这是我得到的错误信息。

[1 of 1] Compiling Main             ( test.hs, interpreted )

test.hs:1:6:
Illegal datatype context (use -XDatatypeContexts): Eq a =>
Failed, modules loaded: none.

这里有什么错误?

谢谢


3个回答

38

你的教授可能在使用较旧版本的 GHC。你发布的代码行使用了最近删除的一个特性。可能的解决方案有:

  1. 移除 Eq a =>,并写成 data Shape a = Shape a

  2. 如 GHC 所说,给出 -XDatatypeContexts 标志以重新启用已删除的特性。

更详细地说,你的类型声明中的 Eq a => 部分称为 数据类型上下文。它唯一的功能是限制 Shape 构造器的类型,使得你能够得到 Shape :: Eq a => a -> Shape a 而不是 Shape :: a -> Shape a。它并不能让你省略涉及 Shape 的类型签名中的 Eq a,实际上甚至会在你本来不需要写的情况下强制你写上它们。在数据类型中使用严格字段需要类约束时,这个特性曾经很有用,但那个特性早已被删除了。

简而言之,仅仅移除上下文几乎总是对你的程序的改进,因此它们已经从 Haskell 2011 语言标准中删除。自 GHC 7.0.1 起提供了关闭它们的选项,自 7.2.1 起成为默认设置。


这样的限制的目的肯定不是为了让我少写点什么,而是通过强制我写更多的内容来提高类型安全性,对吧? - Psachnodaimonia
抱歉,类型安全并不是我要找的词。我认为添加上下文可以更紧密地联系程序的语法可能性和我的语义意图,这样做类型检查将使某些语义错误变得不可能。 - Psachnodaimonia
@Psachnodaimonia:这不是一个不合理的观点,但我认为这个特定的功能更令人困惑而不是有帮助,因为许多人期望它的行为与实际情况不同。 - Ben Millwood
7.8.3: 警告:-XDatatypeContexts已弃用:它被广泛认为是错误的功能,并已从Haskell语言中删除。 - user4256763
我不明白为什么这是不必要的或“非法”的。 没有它,我遇到了这个问题: “没有(Eq a)的实例出现在‘==’的使用中 可能的解决方法:将(Eq a)添加到实例声明的上下文中” 但是当我尝试添加它时: “非法数据类型上下文(使用DatatypeContexts):Eq a =>” 显然,编译器无法确定。 - Timothy Swan
@TimothySwan:将(Eq a)添加到实例声明的上下文中,而不是数据类型。 - Ben Millwood

7

我认为错误信息已经很明确地说明了。你需要一个扩展程序。

{-# LANGUAGE DatatypeContexts #-}
data Eq a => Foo a = Foo a

虽然此扩展曾经默认情况下启用,但从ghc 7.6开始,其使用被视为已弃用,并将来被删除。因此,您的教授可能正在使用较旧版本的ghc。

不是每次都添加那行代码(我也不确定它的确切作用) ,我决定使用 data Foo a = Foo a deriving Eq 谢谢您的提问 :) - Goutham
1
它限制了类型Foo可以采取的方式,以具有Eq实例。假设Bar是一种没有任何Eq实例的类型,则无法拥有类型Foo Bar。另一方面,派生Eq将为Foo派生默认的Eq实例。您可以拥有一个类型Foo Bar(其中Bar没有Eq实例),但不能在其上使用== - Satvik

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接