I'm trying to understand State newtype and I'm struggling with this explanation of the isomorphism in a book:
Newtypes must have the same underlying representation as the type they wrap, as the newtype wrapper disappears at compile time. So the function contained in the newtype must be isomorphic to the type it wraps. That is, there must be a way to go from the newtype to the thing it wraps and back again without losing information.
What does it mean applied to State newtype?
newtype State s a = State { runState :: s -> (a, s) }
That explanation "there must be a way to go from the newtype to the thing it wraps and back again" isn't clear.
Also, can you please say, where there is an isomorphism in this examples, where is not and why.
type Iso a b = (a -> b, b -> a)
newtype Sum a = Sum { getSum :: a }
sumIsIsomorphicWithItsContents :: Iso a (Sum a)
sumIsIsomorphicWithItsContents = (Sum, getSum)
(a -> Maybe b, b -> Maybe a)
[a] -> a, a -> [a]
The statement you quote makes no mention of State specifically. It is purely a statement about newtypes. It is a little misleading in referring to "the function contained in the newtype" because there is no requirement for the type wrapped by a newtype to be a function type - although this is the case for State and many other commonly used types defined by newtype.
The key thing for a newtype in general is exactly as it says: it has to simply wrap another type in a way that makes it trivial to go from the wrapped type to the wrapping one, and vice versa, with no loss of information - this is what it means for two types to be isomorphic, and also what makes it completely safe for the two types to have identical runtime representations.
It's easy to demonstrate typical data declarations that could not possibly fulfil this. For example take any type with 2 constructors, such as Either:
data Either a b = Left a | Right b
It's obvious that this is not isomorphic to either of its constituent types. For example, the Left constructor embeds a inside Either a b, but you can't get any of the Right values this way.
And even with a single constructor, if it takes more than one argument - such as the tuple constructor (,) - then again, you can embed either of the constituent types (given an arbitrary value of the other type) but you can't possibly get every value.
This is why the newtype keyword is only allowed for types with a single constructor which takes a single argument. This always provides an isomorphism, because given newtype Foo a = Foo a, then Foo constructor and the function \Foo a -> a are trivially inverses of each other. And this works the same for more complicated examples where the type constructor takes more type arguments, and/or where the wrapped type is more complex.
Such is exactly the case with State:
newtype State s a = State {runState :: s -> (a, s)}
The functions State and runState respectively wrap and unwrap the underlying type (which in this case is a function), and clearly are inverse to each other - therefore they provide an isomorphism.
Note finally that there is nothing special here about the use of record syntax in the definition - although it's very common in such cases in order to have an already-named "unwrapping" function. Other than this small convenience there is no difference from a newtype defined without record syntax.
To step back a little: newtype declarations are very similar to data declarations with a single constructor and a single argument - the difference is mainly in performance, as the keyword tells the compiler that the two types are equivalent so that there is no runtime overhead of conversion between the two types, which there otherwise would be. (There is also a difference with regard to laziness but I won't mention that, except here for completeness.) As for why do this rather than just use the underlying type - that's to provide extra type safety (there are 2 different types here for the compiler even though they're the same at runtime), and also allows typeclass instances to be specified without attaching those to the underlying type. Sum and Product are great examples here, as they provide Monoid instances for numeric types, based on addition and multiplication respectively, without giving either the undeserved distinction of being "the" Monoid instance for the underlying type.
And something similar is at work with State - when we use this type we signal explicitly that we're using it to represent state manipulation, which wouldn't be the case if we were just working with ordinary functions that happen to return a pair.
Related
I’m trying to understand the applicative typeclass, and in particular the <*> function. Now I see its type signature is f (a -> b) -> f a -> f b and I take it that f is a functor, which I think of as some kind of structure wrapping some data. It appears to me that f must handle generic types, specifically it must be possible for f to have the parameterized types a, b, and in fact it must also support a -> b.
If my understanding is correct, then what we are doing is working with a typeclass f that is initially intended to wrap some data, like say a list of strings or a tree containing file buffers or whatever random thing we might want. But f must not be committed to any one type, because not only must it handle such a type but it is also required to handle functions from the data to the other data. Thus if we had an example implementation of <*> which contained
Just2 f <*> j = fmap f j
the way to read this is that j is some kind of data inside of a Just2. f is a function which maps data to data. And f is wrapped in a Just2.
Is all of that right? Fundamentally my question is: Must anything applicative be so generic that it can always simultaneously handle arbitrary data and also functions from data to data? Or is there some way that you could have an applicative such that the only data it allows inside is, say, lists?
Yes, your understanding is largely correct. In particular, any specific Applicative, say one named Foo, has an associated specialization of the function pure with type signature:
pure :: a -> Foo a
that must work for any type a selected by the caller, such as:
> pure 10 :: Foo Int
> pure length :: Foo (String -> Int)
So, whatever Foo is, it has to be able to "handle" any provided type without limitations because pure can technically be applied to any type without limitations.
One cautionary note, though. The idea that a functor f "wraps" data, so that f Int is somehow a "container" of Int values, can be a helpful intuition and is often literally correct (e.g., lists, trees, etc.), but it's not always strictly true. (Some counterexamples include the functors IO, (->) r, and Const b, which "contain" values in a very different sense than real containers.)
For "regular" Functors and Applicatives, you're right; they need to be able to handle values of any type. This is known as parametric polymorphism. If you have a type that you think is almost a Functor except that it can't do that, then consider the MonoFunctor typeclass from the mono-traversable package. It's the same idea as Functor, except with a single valid element type baked in. I'm not aware of any packages that have a monomorphic equivalent to Applicative. I think this is because <*> uses values of 3 different types inside the same container, so it doesn't have a good monomorphic analogue.
From your question, it sounds like there could be many different Applicative typeclasses. But there is only one; therefore it has to be generic.
The Applicative typeclass is defined by its functions (<*> and pure) and by the laws these functions need to adhere to. In any Haskell codebase, there can be exactly one definition only. But there can be many types that have an instance of the Applicative typeclass. You can define your own instances with the instance declaration and by defining the required functions. The compiler will not check that your definitions abide by the functor laws, though - this is up to you to ensure.
Typeclasses like Functor, Applicative and Monad do not specify a data type; they don't say that you need a "list-like" type, or a "box-like" type, event though lists and other containers like Either do have instances of these type classes. Any type that you can equip with the required functions in such a way that the Applicative laws hold becomes an Applicative.
It is often helpful to think of containers or boxes. But you need to stretch that intuition once you use Applicative instances of types like functions; e.g., a -> r.
Compared with interfaces in OO-languages, typeclasses are more powerful because you can define some data type to be an instance of a typeclass even if you do not have access to the source code of the type itself.
Why do we need Control.Lens.Reified? Is there some reason I can't place a Lens directly into a container? What does reify mean anyway?
We need reified lenses because Haskell's type system is predicative. I don't know the technical details of exactly what that means, but it prohibits types like
[Lens s t a b]
For some purposes, it's acceptable to use
Functor f => [(a -> f b) -> s -> f t]
instead, but when you reach into that, you don't get a Lens; you get a LensLike specialized to some functor or another. The ReifiedBlah newtypes let you hang on to the full polymorphism.
Operationally, [ReifiedLens s t a b] is a list of functions each of which takes a Functor f dictionary, while forall f . Functor f => [LensLike f s t a b] is a function that takes a Functor f dictionary and returns a list.
As for what "reify" means, well, the dictionary will say something, and that seems to translate into a rather stunning variety of specific meanings in Haskell. So no comment on that.
The problem is that, in Haskell, type abstraction and application are completely implicit; the compiler is supposed to insert them where needed. Various attempts at designing 'impredicative' extensions, where the compiler would make clever guesses where to put them, have failed; so the safest thing ends up being relying on the Haskell 98 rules:
Type abstractions occur only at the top level of a function definition.
Type applications occur immediately whenever a variable with a polymorphic type is used in an expression.
So if I define a simple lens:[1]
lensHead f [] = pure []
lensHead f (x:xn) = (:xn) <$> f x
and use it in an expression:
[lensHead]
lensHead gets automatically applied to some set of type parameters; at which point it's no longer a lens, because it's not polymorphic in the functor anymore. The take-away is: an expression always has some monomorphic type; so it's not a lens. (You'll note that the lens functions take arguments of type Getter and Setter, which are monomorphic types, for similar reasons to this. But a [Getter s a] isn't a list of lenses, because they've been specialized to only getters.)
What does reify mean? The dictionary definition is 'make real'. 'Reifying' is used in philosophy to refer to the act of regarding or treating something as real (rather than ideal or abstract). In programming, it tends to refer to taking something that normally can't be treated as a data structure and representing it as one. For example, in really old Lisps, there didn't use to be first-class functions; instead, you had to use S-Expressions to pass 'functions' around, and eval them when you needed to call the function. The S-Expressions represented the functions in a way you could manipulate in the program, which is referred to as reification.
In Haskell, we don't typically need such elaborate reification strategies as Lisp S-Expressions, partly because the language is designed to avoid needing them; but since
newtype ReifiedLens s t a b = ReifiedLens (Lens s t a b)
has the same effect of taking a polymorphic value and turning it into a true first-class value, it's referred to as reification.
Why does this work, if expressions always have monomorphic types? Well, because the Rank2Types extension adds a third rule:
Type abstractions occur at the top-level of the arguments to certain functions, with so-called rank 2 types.
ReifiedLens is such a rank-2 function; so when you say
ReifiedLens l
you get a type lambda around the argument to ReifiedLens, and then l is applied immediately to the the lambda-bound type argument. So l is effectively just eta-expanded. (Compilers are free to eta-reduce this and just use l directly).
Then, when you say
f (ReifiedLens l) = ...
on the right-hand side, l is a variable with polymorphic type, so every use of l is immediately implicitly assigned to whatever type arguments are needed for the expression to type-check. So everything works the way you expect.
The other way to think about is that, if you say
newtype ReifiedLens s t a b = ReifiedLens { unReify :: Lens s t a b }
the two functions ReifiedLens and unReify act like explicit type abstraction and application operators; this allows the compiler to identify where you want the abstractions and applications to take place well enough that the issues with impredicative type systems don't come up.
[1] In lens terminology, this is apparently called something other than a 'lens'; my entire knowledge of lenses comes from SPJ's presentation on them so I have no way to verify that. The point remains, since the polymorphism is still necessary to make it work as both a getter and a setter.
I was revisiting a piece of code I wrote to do combinatorial search a few months ago, and noticed that there was an alternative, simpler way to do something that I'd previously achieved with a type class.
Specifically, I previously had a type class for the type of search problems, which have an states of type s, actions (operations on states) of type a, an initial state, a way of getting a list of (action,state) pairs and a way of testing whether a state is a solution or not:
class Problem p s a where
initial :: p s a -> s
successor :: p s a -> s -> [(a,s)]
goaltest :: p s a -> s -> Bool
This is somewhat unsatisfactory, as it requires the MultiParameterTypeClass extension, and generally needs FlexibleInstances and possibly TypeSynonymInstances when you want to make instances of this class. It also clutters up your function signatures, e.g.
pathToSolution :: Problem p => p s a -> [(a,s)]
I noticed today that I can get rid of the class entirely, and use a type instead, along the following lines
data Problem s a {
initial :: s,
successor :: s -> [(a,s)],
goaltest :: s -> Bool
}
This doesn't require any extensions, the function signatures look nicer:
pathToSolution :: Problem s a -> [(a,s)]
and, most importantly, I found that after refactoring my code to use this abstraction instead of a type class, I was left with 15-20% fewer lines than I had previously.
The biggest win was in code that created abstractions using the type class - previously I had to create new data structures that wrapped the old ones in a complicated way, and then make them into instances of the Problem class (which required more language extensions) - lots of lines of code to do something relatively simple. After the refactor, I just had a couple of functions that did exactly what I wanted to.
I'm now looking through the rest of the code, trying to spot instances where I can replace type classes with types, and make more wins.
My question is: in what situation does will this refactoring not work? In what cases is it actually just better to use a type class rather than a data type, and how can you recognise those situations ahead of time, so you don't have to go through a costly refactoring?
Consider a situation where both the type and class exist in the same program. The type can be an instance of the class, but that's rather trivial. More interesting is that you can write a function fromProblemClass :: (CProblem p s a) => p s a -> TProblem s a.
The refactoring you performed is roughly equivalent to manually inlining fromProblemClass everywhere you construct something used as a CProblem instance, and making every function that accepts a CProblem instance instead accept TProblem.
Since the only interesting parts of this refactoring are the definition of TProblem and the implementation of fromProblemClass, if you can write a similar type and function for any other class, you can likewise refactor it to eliminate the class entirely.
When does this work?
Think about the implementation of fromProblemClass. You'll essentially be partially applying each function of the class to a value of the instance type, and in the process eliminating any reference to the p parameter (which is what the type replaces).
Any situation where refactoring away a type class is straightforward is going to follow a similar pattern.
When is this counterproductive?
Imagine a simplified version of Show, with only the show function defined. This permits the same refactoring, applying show and replacing each instance with... a String. Clearly we've lost something here--namely, the ability to work with the original types and convert them to a String at various points. The value of Show is that it's defined on a wide variety of unrelated types.
As a rule of thumb, if there are many different functions specific to the types which are instances of the class, and these are often used in the same code as the class functions, delaying the conversion is useful. If there's a sharp dividing line between code that treats the types individually and code that uses the class, conversion functions might be more appropriate with a type class being a minor syntactic convenience. If the types are used almost exclusively through the class functions, the type class is probably completely superfluous.
When is this impossible?
Incidentally, the refactoring here is similar to the difference between a class and interface in OO languages; similarly, the type classes where this refactoring is impossible are those which can't be expressed directly at all in many OO languages.
More to the point, some examples of things you can't translate easily, if at all, in this manner:
The class's type parameter appearing only in covariant position, such as the result type of a function or as a non-function value. Notable offenders here are mempty for Monoid and return for Monad.
The class's type parameter appearing more than once in a function's type may not make this truly impossible but it complicates matters quite severely. Notable offenders here include Eq, Ord, and basically every numeric class.
Non-trivial use of higher kinds, the specifics of which I'm not sure how to pin down, but (>>=) for Monad is a notable offender here. On the other hand, the p parameter in your class is not an issue.
Non-trivial use of multi-parameter type classes, which I'm also uncertain how to pin down and gets horrendously complicated in practice anyway, being comparable to multiple dispatch in OO languages. Again, your class doesn't have an issue here.
Note that, given the above, this refactoring is not even possible for many of the standard type classes, and would be counterproductive for the few exceptions. This is not a coincidence. :]
What do you give up by applying this refactoring?
You give up the ability to distinguish between the original types. This sounds obvious, but it's potentially significant--if there are any situations where you really need to control which of the original class instance types was used, applying this refactoring loses some degree of type safety, which you can only recover by jumping through the same sort of hoops used elsewhere to ensure invariants at run-time.
Conversely, if there are situations where you really need to make the various instance types interchangeable--the convoluted wrapping you mentioned being a classic symptom of this--you gain a great deal by throwing away the original types. This is most often the case where you don't actually care much about the original data itself, but rather about how it lets you operate on other data; thus using records of functions directly is more natural than an extra layer of indirection.
As noted above, this relates closely to OOP and the type of problems it's best suited to, as well as representing the "other side" of the Expression Problem from what's typical in ML-style languages.
Your refactoring is closely related to this blog entry by Luke Palmer: "Haskell Antipattern: Existential Typeclass".
I think we can prove that your refactoring will always work. Why? Intuitively, because if some type Foo contains enough information so that we can make it into an instance of your Problem class, we can always write a Foo -> Problem function that "projects" Foo's relevant information into a Problem that contains exactly the information needed.
A bit more formally, we can sketch a proof that your refactoring always works. First, to set the stage, the following code defines a translation of a Problem class instance into a concrete CanonicalProblem type:
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
class Problem p s a where
initial :: p s a -> s
successor :: p s a -> s -> [(a,s)]
goaltest :: p s a -> s -> Bool
data CanonicalProblem s a = CanonicalProblem {
initial' :: s,
successor' :: s -> [(a,s)],
goaltest' :: s -> Bool
}
instance Problem CanonicalProblem s a where
initial = initial'
successor = successor'
goaltest = goaltest'
canonicalize :: Problem p s a => p s a -> CanonicalProblem s a
canonicalize p = CanonicalProblem {
initial' = initial p,
successor' = successor p,
goaltest' = goaltest p
}
Now we want to prove the following:
For any type Foo such that instance Problem Foo s a, it is possible to write a canonicalizeFoo :: Foo s a -> CanonicalProblem s a function that produces the same result as canonicalize when applied to any Foo s a.
It's possible to rewrite any function that uses the Problem class into an equivalent function that uses CanonicalProblem instead. E.g., if you have solve :: Problem p s a => p s a -> r, you can write a canonicalSolve :: CanonicalProblem s a -> r that's equivalent to solve . canonicalize
I'll just sketch proofs. In the case of (1), suppose you have a type Foo with this Problem instance:
instance Problem Foo s a where
initial = initialFoo
successor = successorFoo
goaltest = goaltestFoo
Then given x :: Foo s a you can trivially prove the following by substitution:
-- definition of canonicalize
canonicalize :: Problem p s a => p s a -> CanonicalProblem s a
canonicalize x = CanonicalProblem {
initial' = initial x,
successor' = successor x,
goaltest' = goaltest x
}
-- specialize to the Problem instance for Foo s a
canonicalize :: Foo s a -> CanonicalProblem s a
canonicalize x = CanonicalProblem {
initial' = initialFoo x,
successor' = successorFoo x,
goaltest' = goaltestFoo x
}
And the latter can be used directly to define our desired canonicalizeFoo function.
In the case of (2), for any function solve :: Problem p s a => p s a -> r (or similar types that involve Problem constraints), and for any type Foo such that instance Problem Foo s a:
Define canonicalSolve :: CanonicalProblem s a -> r' by taking the definition of solve and substituting all occurrences of Problem methods with their CanonicalProblem instance definitions.
Prove that for any x :: Foo s a, solve x is equivalent to canonicalSolve (canonicalize x).
Concrete proofs of (2) require concrete definitions of solve or related functions. A general proof could go either of these two ways:
Induction over all types that have Problem p s a constraints.
Prove that all Problem functions can be written in terms of a small subset of the functions, prove that this subset has CanonicalProblem equivalents, and that the various ways of using them together preserves the equivalence.
If you are from OOP backaground. You can think of typeclasses as interfaces in java. They are generally used when you want to provide same interface to different data types, generally involving data type specific implementations for each.
In your case there is no use of using a typeclass, it will only over complicate your code.
for more informaction you can always refer to haskellwiki for better understanding.
http://www.haskell.org/haskellwiki/OOP_vs_type_classes
The general rule of thumb is: If you are doubtful whether you need type classes or not, then you probably don't need them.
Does Haskell, or a specific compiler, have anything like type-level lambdas (if that's even a term)?
To elaborate, say I have a parametrized type Foo a b and want Foo _ b to be an instance of, say, Functor. Is there any mechanism that would let me do something akin to
instance Functor (\a -> Foo a b) where
...
?
While sclv answered your direct question, I'll add as an aside that there's more than one possible meaning for "type-level lambda". Haskell has a variety of type operators but none really behave as proper lambdas:
Type constructors: Abstract type operators that introduce new types. Given a type A and a type constructor F, the function application F A is also a type but carries no further (type level) information than "this is F applied to A".
Polymorphic types: A type like a -> b -> a implicitly means forall a b. a -> b -> a. The forall binds the type variables within its scope, thus behaving somewhat like a lambda. If memory serves me this is roughly the "capital lambda" in System F.
Type synonyms: A limited form of type operators that must be fully applied, and can produce only base types and type constructors.
Type classes: Essentially functions from types/type constructors to values, with the ability to inspect the type argument (i.e., by pattern matching on type constructors in roughly the same way that regular functions pattern match on data constructors) and serving to define a membership predicate on types. These behave more like a regular function in some ways, but are very limited: type classes aren't first-class entities that can be manipulated, and they operate on types only as input (not output) and values only as output (definitely not input).
Functional dependencies: Along with some other extensions, these allow type classes to implicitly produce types as results as well, which can then be used as the parameters to other type classes. Still very limited, e.g. by being unable to take other type classes as arguments.
Type families: An alternate approach to what functional dependencies do; they allow functions on types to be defined in a manner that looks much closer to regular value-level functions. The usual restrictions still apply, however.
Other extensions relax some of the restrictions mentioned, or provide partial workarounds (see also: Oleg's type hackery). However, pretty much the one thing you can't do anywhere in any way is exactly what you were asking about, namely introduce new a binding scope with an anonymous function abstraction.
From TypeCompose:
newtype Flip (~>) b a = Flip { unFlip :: a ~> b }
http://hackage.haskell.org/packages/archive/TypeCompose/0.6.3/doc/html/Control-Compose.html#t:Flip
Also, if something is a Functor in two arguments, you can make it a bifunctor:
http://hackage.haskell.org/packages/archive/category-extras/0.44.4/doc/html/Control-Bifunctor.html
(or, in a later category-extras, a more general version: http://hackage.haskell.org/packages/archive/category-extras/0.53.5/doc/html/Control-Functor.html#t:Bifunctor)
I don't like the idea of answering my own question, but apparently, according to several people on #haskell on Freenode, Haskell doesn't have type-level lambdas.
EHC (and perhaps also its successor, UHC) has type-level lambdas, but they are undocumented and not as powerful as in a dependently-typed language. I recommend you use a dependently-typed language such as Agda (similar to Haskell) or Coq (different, but still pure functional at its core, and can be interpreted and compiled either lazily or strictly!) But I'm biased towards such languages, and this is probably 100x overkill for what you are asking for here!
The closest I know of to get a type lambda is by defining a type synonym. In your example,
data Foo a b = Foo a b
type FooR a b = Foo b a
instance Functor (FooR Int) where
...
But even with -XTypeSynonymInstances -XFlexibleInstances this doesn't work; GHC expects the type syn to be fully applied in the instance head. There may be some way to arrange it with type families.
Yeah, what Gabe said, which is somewhat answered by type families:
http://www.haskell.org/haskellwiki/GHC/Type_families
Depending on the situation, you could replace your original type definition with a "flipped" version, and then make a type synonym for the "correct" version.
From
data X a b = Y a b
instance Functor (\a -> X a b) where ...
to
data XFlip b a = Y a b -- Use me for instance decalarations
type X a b = XFlip b a -- Use me for everything else
instance Functor XFlip where ...
Firstly, this question isn't 100% specific to Haskell, feel free to comment on the general design of typeclasses, interfaces and types.
I'm reading LYAH - creating types and typeclasses The following is the passage that I'm looking for more information on:
Data (Ord k) => Map k v = ...
However, it's a very strong convention
in Haskell to never add typeclass
constraints in data declarations. Why?
Well, because we don't benefit a lot,
but we end up writing more class
constraints, even when we don't need
them. If we put or don't put the Ord k
constraint in the data declaration for
Map k v, we're going to have to put
the constraint into functions that
assume the keys in a map can be
ordered. But if we don't put the
constraint in the data declaration, we
don't have to put (Ord k) => in the
type declarations of functions that
don't care whether the keys can be
ordered or not. An example of such a
function is toList, that just takes a
mapping and converts it to an
associative list. Its type signature
is toList :: Map k a -> [(k, a)]. If
Map k v had a type constraint in its
data declaration, the type for toList
would have to be toList :: (Ord k) =>
Map k a -> [(k, a)], even though the
function doesn't do any comparing of
keys by order.
This at first, seems logical -- but isn't there an upside to having the typeclass attached to the type? If the typeclass is the behavior of the type, then why should the behavior be defined by the use of the type (through functions), and not the type itself? I assume there is some meta-programming that could make use of it, and it is certainly nice and descriptive code-documentation. Conversely, would this be a good idea in other languages? Would it be ideal to specify the interface the object should conform to on the method, such that if the method isn't used by the caller the object doesn't have to conform to the interface? Moreover, why can Haskell not infer that a function using type Foo, has to pull in the typeclass constraints identified in type Foo's declaration? Is there a pragma to enable this?
The first time I read it, it conjured a "that's a hack (or workaround) response". On second read with some thought, it sounded clever. On third read, drawing a compairison to the OO world, it sounded like a hack again.
So here I am.
Perhaps Map k v wasn't the best example to illustrate the point. Given the definition of Map, even though there are some functions that won't need the (Ord k) constraint, there is no possible way to construct a Map without it.
One often finds that a type is quite usable with the sub-set of functions that work on without some particular constraint, even when you envisioned the constraint as an obvious aspect of your original design. In such cases, having left the constraint off the type declaration leaves it more flexible.
For example, Data.List contains plenty of functions that require (Eq a), but of course lists are perfectly useful without that constraint.
The short answer is: Haskell does this because that's how the language spec is written.
The long answer involves quoting from the GHC documentation language extensions section:
Any data type that can be declared in standard Haskell-98 syntax can also be declared using GADT-style syntax. The choice is largely stylistic, but GADT-style declarations differ in one important respect: they treat class constraints on the data constructors differently. Specifically, if the constructor is given a type-class context, that context is made available by pattern matching. For example:
data Set a where
MkSet :: Eq a => [a] -> Set a
(...)
All this behaviour contrasts with Haskell 98's peculiar treatment of contexts on a data type declaration (Section 4.2.1 of the Haskell 98 Report). In Haskell 98 the definition
data Eq a => Set' a = MkSet' [a]
gives MkSet' the same type as MkSet above. But instead of making available an (Eq a) constraint, pattern-matching on MkSet' requires an (Eq a) constraint! GHC faithfully implements this behaviour, odd though it is. But for GADT-style declarations, GHC's behaviour is much more useful, as well as much more intuitive.
The main reason to avoid typeclass constraints in data declarations is that they accomplish absolutely nothing; in fact, I believe GHC refers to such a class context as the "stupid context". The reason for this is that the class dictionary is not carried around with the values of the data type, so you have to add it to every function operating on the values anyway.
As a way of "forcing" the typeclass constraint on functions operating on the data type, it also doesn't really accomplish anything; functions should generally be as polymorphic as possible, so why force the constraint onto things that don't need it?
At this point, you might think that it should be possible to change the semantics of ADTs in order to carry the dictionary around with the values. In fact, it seems like this is the whole point of GADTs; for example, you can do:
data Foo a where { Foo :: (Eq a) => a -> Foo a }
eqfoo :: Foo t -> Foo t -> Bool
eqfoo (Foo a) (Foo b) = a == b
Notice that the type of eqfoo does not need the Eq constraint, as it is "carried" by the Foo data type itself.
I would like to point out that if you are worried that one could construct an object that requires constraints for its operations but doesn't for its creation, say mkFoo, you can always artifically put the constraint on the mkFoo function to enforce the use of the typeclass by people who use the code. The idea also extends to non mkFoo type functions that operate on Foo. Then when defining the module, don't export anything that doesn't enforce the constraints.
Though I have to admit, I don't see any use for this.