DatatypeContexts Deprecated in Latest GHC: Why?
Asked Answered
O

2

79

I was just doing some Haskell development and I recompiled some old code on a new version of GHC:

The Glorious Glasgow Haskell Compilation System, version 7.2.1

And when I did I received the following error:

Warning: -XDatatypeContexts is deprecated: It was widely considered a misfeature, and has been removed from the Haskell language.

That appears when you have code in the following format:

data Ord a => MyType a
    = ConstructorOne a
    | ConstructorTwo a a

My question is: Why was this feature deprecated in the first place and what am I supposed to do instead to achieve the same or similar functionality?

Orchestrion answered 15/9, 2011 at 23:28 Comment(3)
Just remove the context and your code will still work.Tsarism
If you're getting a related error when trying cabal install <package>, then try cabal install --ghc-option '-XDataTypeContexts' <package>.Marinna
@Marinna As an answer suggested, maybe the command should contain -XDatatypeContexts without a lowercase t.Viehmann
B
110

It's deprecated because it was a misfeature, and didn't actually have any useful functionality! All it did was force a bunch of extra constraints in other locations. In particular, when pattern matching on such a type, you'd be forced to add a constraint, rather than (as one might initially hope) get access to a context, based on the knowledge that one must have been available to construct the value in the first place.

The "replacement", which actually works the other way and tracks the known contexts for you, is to use GADT-style declarations instead:

data MyType a where
    ConstructorOne :: Ord a => a -> MyType a
    ConstructorTwo :: Ord a => a -> a -> MyType a

GADTs in general are more flexible in many other ways as well, but for this particular case what happens is that creating a value needs the Ord constraint, which is then carried along with the value, and pattern matching on the constructor pulls it back out. So you don't even need the context on the functions using it, because you know that by virtue of expecting something of type MyType a, you'll get an Ord a constraint with it.

Butacaine answered 15/9, 2011 at 23:46 Comment(4)
The last sentence seems a bit unclear-what you pull from the GADT constructor is not the constraint but rather the instance(s) satisfying the constraint.Trend
But if there are too many constructors doesn't it become too verbose to repeat Ord a for each one?Imminence
@Imminence I mean this shouldn't come up often anyway. You almost always don't want to restrict your types like that. One example for why is that it makes it impossible to make your type a Functor, Foldable, Traversable, Applicative, Monad, Alternative, MonadPlus, Arrow and so on.Pomiferous
GADTs are very nice because I can have some more restricted constructors in certain cases, and I have found that to be useful in those cases. Thanks for the answer.Tridimensional
K
13

In general, you still need to add the Ord a constraint to any function which uses your MyType type, and as such isn't as useful as it may seem. For more information about why they were removed, see http://hackage.haskell.org/trac/haskell-prime/wiki/NoDatatypeContexts

Kep answered 15/9, 2011 at 23:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.