In Haskell, one can define a data type like so:
data Point1 = Point1 {
x :: Integer
, y :: Integer
}
Can one use type classes for variables inside a data type? If so how? I realize it is possible to do this as an algebraic data type, with a different definition for each kind of point, but I'm wondering if there's a way to accomplish this in a more compact and flexible manner.
e.g. Something along the lines of this pseudocode which uses function declaration syntax:
data Point2 = Point2 {
x :: (Num a, Ord a) => a
, y :: (Num a, Ord a) => a
}
The goal would be to allow one to store Int, Integer, Float or Double values in the data type. Ideally, I'd like to restrict it so that x and y must be of the same type.
Type Classes are a language mechanism in Haskell designed to support general overloading in a principled way. They address each of the concerns raised above. They provide concise types to describe overloaded functions, so there is no expo- nential blow-up in the number of versions of an overloaded function.
The classes used by Haskell are similar to those used in other object-oriented languages such as C++ and Java. However, there are some significant differences: Haskell separates the definition of a type from the definition of the methods associated with that type.
In computer science, a type class is a type system construct that supports ad hoc polymorphism. This is achieved by adding constraints to type variables in parametrically polymorphic types.
You need to decide if you want an existential or universal quantification on that type. Universal quantification, ala:
data (Num a, Ord a) => Point2 a = Point2 a a
yields a proof obligation that Num and Ord instances exist for the type 'a' but doesn't actually help all that much, because all it does is give you an obligation when you go to use the Point class by constructing a value of that type or when you go to pattern match it.
In almost all cases you are better off defining
data Point2 a = Point2 a a deriving (Eq,Ord,Show,Read)
and making each of your instances contingent on the extra information you want.
instance Num a => Num (Point2 a) where
...
instance (Num a, Ord a) => SomeClass (Point2 a) where
...
This lets you pass around and construct fewer superfluous dictionaries and increases the number of scenarios in which your Point2 data type can be used.
On the other hand existential quantification can let you say that you don't care what the type is at all (closer to what you actually requested, type wise) at the expense that you can't use anything on it except for the operations provided by the constraints you specified -- a pretty poor fit here.
something like this?
data (Num a, Ord a) => Point2 a = Point2 {
x :: a
, y :: a
}
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