If I have an ADT with specified typeclass restrictions I still have to specify the same typeclass for each function using this data type. What the reason for this and how can I reduce unnecessary typing?
E.g.:
data Eq a => C a = V a
g :: C a -> Bool
g (V a) = a == a
I got:
test.hs:32:13:
No instance for (Eq a)
arising from a use of `=='
In the expression: a == a
In an equation for `g': g (V a) = a == a
Failed, modules loaded: none.
While:
g :: Eq a => C a -> Bool
Works fine, but if I have a long chain of functions it becomes a burden to specify a typeclass everytime:
f :: Eq a => C a -> Bool
f a = g a
What's a typeclass in Haskell? A typeclass defines a set of methods that is shared across multiple types. For a type to belong to a typeclass, it needs to implement the methods of that typeclass. These implementations are ad-hoc: methods can have different implementations for different types.
The Data Keyword and Constructors In general, we define a new data type by using the data keyword, followed by the name of the type we're defining. The type has to begin with a capital letter to distinguish it from normal expression names. To start defining our type, we must provide a constructor.
Type and data type refer to exactly the same concept. The Haskell keywords type and data are different, though: data allows you to introduce a new algebraic data type, while type just makes a type synonym. See the Haskell wiki for details.
The Eq typeclass provides an interface for testing for equality. Any type where it makes sense to test for equality between two values of that type should be a member of the Eq class. All standard Haskell types except for IO (the type for dealing with input and output) and functions are a part of the Eq typeclass.
It's generally considered a bad idea to put a typeclass restriction on your ADT. Instead, leave it off and code normally using (==)
wherever you have to. Your Eq a
dependency will percolate up some of your functions and not others.
Because the Haskell Report says so, basically. It's generally regarded as somewhat silly. Quoth the GHC User Guide:
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.
Putting contexts on regular data definitions is discouraged and may (will?) be removed from the language at some point. Either put the context only on the function (which is what actually needs it, anyhow), or use GADT-style syntax to get the behavior you expected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With