29

I am not able to get this line of code compiled in Haskell but it works on my professor's system. I use ghci version 7.6.2.

data Eq a => Shape a = Shape a

More precisely, this is the error I am getting

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

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

What is the mistake here?

Thanks

Ben Millwood
  • 6,754
  • 24
  • 45
Goutham
  • 293
  • 3
  • 7
  • Possible duplicate of [How to fix "Illegal datatype context" (use -XDatatypeContexts)?](http://stackoverflow.com/questions/22622399/how-to-fix-illegal-datatype-context-use-xdatatypecontexts) – wizzup Apr 19 '17 at 06:53

3 Answers3

38

Your professor is probably using an older version of GHC. The line you posted uses a feature which has quite recently been removed. The possible solutions are:

  1. Remove Eq a => and write data Shape a = Shape a.

  2. As GHC says, give the -XDatatypeContexts flag to re-enable the removed feature.

In more detail: the Eq a => part of your type declaration is called a datatype context. Its only function is to restrict the type of the Shape constructor, so that instead of Shape :: a -> Shape a you get Shape :: Eq a => a -> Shape a. It does not save you from having to write Eq a in type signatures involving Shapes, and indeed will even require you to write them when you wouldn't otherwise need to. It was once useful when strict fields in datatypes required a class constraint, but that feature was removed long ago.

In short, just removing the context is nearly always an improvement to your program, so they were removed from the Haskell 2011 language standard. Since GHC 7.0.1 there has been an option to turn them off and since 7.2.1 it has been the default.

Ben Millwood
  • 6,754
  • 24
  • 45
  • Surely the purpose of such a restriction isn't to save my having to write something but to improve type safety precisely by forcing me to write more than I would otherwise need to? – Psachnodaimonia Jun 07 '14 at 10:32
  • Sorry, type safety isn't really the word I am looking for. I am thinking that adding the context creates a tighter link between the programs syntactic possibilities and my semantic intention, and in so doing the type checking will make certain semantic errors impossible. – Psachnodaimonia Jun 07 '14 at 10:53
  • @Psachnodaimonia: that's not an unreasonable point of view, but I think this particular feature is more confusing than helpful, since many people expect it to behave differently from how it does. – Ben Millwood Jun 08 '14 at 19:59
  • 7.8.3: _Warning: -XDatatypeContexts is deprecated: It was widely considered a misfeature, and has been removed from the Haskell language._ from `ghci -XDatatypeContexts`. –  Nov 25 '14 at 23:14
  • I don't understand why this is unnecessary or 'illegal'. I have the problem without it: "No instance for (Eq a) arising from a use of ‘==’ Possible fix: add (Eq a) to the context of the instance declaration" But when I try to add it: "Illegal datatype context (use DatatypeContexts): Eq a =>" Apparently, the compiler can't make up its mind. – Timothy Swan May 29 '15 at 01:39
  • @TimothySwan: add (Eq a) to the context of the **instance declaration**, not the datatype. – Ben Millwood May 30 '15 at 22:33
7

I think the error message is clear in what it says. You need an extension for that.

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

Although this extension used to be on by default but starting from ghc 7.6, its usage is considered deprecated and will be removed in the future. So your professor might be using an older version of ghc.

Satvik
  • 11,238
  • 1
  • 38
  • 46
  • Instead of adding that line everytime(I also don't know what it exactly does), I decided to use `data Foo a = Foo a deriving Eq` Thanks for your answer :) – Goutham Sep 22 '13 at 08:26
  • 1
    It constraints the types `Foo` can take, to have Eq instance. Suppose `Bar` is a type without any `Eq` instance, you can not have the type `Foo Bar`. On the other hand deriving `Eq` will derive a default `Eq` instance for `Foo`. You can have a type `Foo Bar` (where `Bar` has no `Eq` instance) but you can not use `==` on it. – Satvik Sep 22 '13 at 12:59
3

See also https://stackoverflow.com/a/22622591/2008899 which explains the "Why?" behind the language change as well as showing a GADT example that does what datatype contexts was supposed to provide.

Community
  • 1
  • 1