Many languages have primitive composite types, like arrays, or structures with named fields, or tuples, or what have you.
The primary primitive composite type in Haskell is the algebraic data type or ADT. It is a "sum of products" or a "tagged union of structures". OOP languages usually have an obvious primitive product (structure) type. In some languages, like C++, there literally is a struct primitive, but in most OOP languages, classes themselves serve as the obvious product type -- you have a bunch of fields defined by the class, and an object is a value that's a product of values for each field.
OOP languages seldom have an obvious primitive sum (tagged union) type. However, there's an implicit one. Every time you call a method on an object and rely on dispatch based on the object's class, you're essentially using a sum (tagged union) type. You have a variable whose type is an interface or an abstract superclass (depending on the language), and the variable's value is an object whose class implements the interface or inherits from the superclass. When you call a method on the variable, the class is consulted to dispatch to the right method. Equivalently, you have a variable whose type is a sum (tagged union); the variable's value corresponds to one component of the sum (member of the tagged union); and when you call a method on the variable, the tag is consulted to determine which component of the sum (member of the tagged union) you actually have, so the correct method implementation can be called.
This analogy isn't as crazy as it appears. Picture in your mind an OOP implementation of a binary tree with integer values in the leaves. You are probably imagining Node and Leaf classes implementing a common Tree interface that provides, say, traversal methods. Now, consider a Haskell implementation:
data Tree = Leaf Int | Node Tree Tree
^^^^-------^^^^- the classes
^^^^- the interface
traverse :: Tree -> [Int]
^^^^^^^^- the method
traverse (Leaf x) = [x]
traverse (Node l r) = traverse l ++ traverse r
In practice, many OOP designs are naturally mapped to Haskell this way, with interfaces, classes, and methods mapping to data types, constructors, and plain old functions.
What does this have to do with your question? Well, if you have a data type like:
data Color = Red | Green | Blue | Indigo | Violet
you shouldn't be thinking of Color as an alias for some other primitive type (e.g., integers) with some mapping of its values Red through Violet to values 1 through 5. This would be like considering the OOP interface Tree as being an alias for some primitive type (what, doubles? strings?) with aliased "values" Node and Leaf corresponding to primitive values like 2.0 or "hello".
Instead, think of Color as the primitive composite type it is -- a sum of products or tagged union of structures, where the products/structures happen to be nullary (with zero fields). As a result, all that's left are the tags for the tagged sum (like Red and so on). There's no "other" primitive type needed for the representation, because the composite sum-of-products primitive type is the underlying primitive type.