You really see two separate problems, so I will consider them as such.
The first is with the value field. Haskell entries work in a somewhat peculiar way: when you name a field, it is automatically added to the current area as a function. Essentially, you can think of
data ListOfInts = ListOfInts {value :: [Int]}
as syntactic sugar for:
data ListOfInts = ListOfInts [Int] value :: ListOfInt -> [Int] value (ListOfInts v) = v
Thus, the presence of two records with the same field name is similar to the presence of two different functions with the same name - they overlap. This is why your first error tells you that you declared values several times.
A way to fix this would be to define your types without using the syntax of the entry, as I did above:
data ListOfInts = ListOfInts [Int] data ListOfDoubles = ListOfDoubles [Double]
When you used type instead of data , you simply created a type synonym, not a new type. Using
type ListOfInts = [Int]
means ListOfInts matches [Int] . For various reasons, you cannot use type synonyms in instances of a class by default. This makes sense - it would be very easy to make a mistake, for example, try to write an instance for [Int] , and also one for ListOfInts , which will break.
Using data to wrap one type of type like [Int] or [Double] same as using newtype . However, newtype has the advantage that it does not incur overhead at runtime. Therefore, the best way to write these types would really be with newtype :
newtype ListOfInts = ListOfInts [Int] newtype ListOfDoubles = ListOfDoubles [Double]
It is important to note that when using data or newtype you also need to "expand" the type if you want to get its contents. You can do this using pattern matching:
instance Incrementable ListOfInts where increment (ListOfInts ls) = ListOfInts (map (\ x -> x + 1) ls)
This expands ListOfInts , displays the function above its contents, and wraps it.
As long as you expand the value this way, your instances should work.
On a side note, you can write map (\ x -> x + 1) as map (+ 1) using something called an “operator section”. All this means that you implicitly create lambda padding depending on which argument of the operator is missing. Most people find the map (+ 1) version easier to read because there is less unnecessary noise.