I want to create a new type of data with Haskell and create the related Show
instances. I need to create the tuple Show instance with another delimiter than ,
.
I implemented this code (with the {-# LANGUAGE FlexibleInstances #-}
pragma):
newtype Data = Data Double
instance Show Data where
show (Data dat) = show dat
instance Show (Data,Data) where
show (Data d1,Data d2) = show d1++" "++show d2
instance Show (Data,Data,Data) where
show (Data d1,Data d2,Data d3) = show d1++" "++show d2++" "++show d3
Is it possible to automatically extend the Show instance to tuples of any size without manually creating the instances?
Note : I'm aware I could use concat $ intersperse " " ...
to intercalate things between list elements. But for many reasons I wish to use tuples rather than lists.
How to write generic code for tuples
This is not supported directly in the language, because tuples in Haskell are all or nothing. In Idris, this would be easy, because (a,b,c)
actually means (a,(b,c))
. Haskell's laziness would make that representation inefficient, and in any case Haskell just has a different concept of what a tuple is. However, you can use generics to write that sort of code! I promise it will be painful.
Why what you're trying to do is a bad idea
The biggest problem is not that you are trying to make generic tuple code. The biggest problem is that your Show
instances overlap the usual ones. The base libraries already export
instance (Show a, Show b) => Show (a, b)
instance (Show a, Show b, Show c) => Show (a,b,c)
etc. When figuring out whether instances overlap, you must look only on the right side of the =>
. So even if your Data
is not in Show
, you have a problem. Haskell insists on committing to a choice of instance before even looking to the left of the arrow. By default, it does this by complaining about overlapping instances if it can't resolve the instance uniquely. If you OverlappingInstances
, you might get it working, but this is not a good use case for that somewhat evil extension. If you use IncoherentInstances
, it will probably work, but that is such a massively evil extension that it is much better to pretend it does not exist at all.
Haskell provides absolutely no way to write code that's polymorphic over tuples of different sizes.
But given that all you seem to be doing is creating tuples of Data
(which is really just Double
), I have to ask... why not just use a list? You can easily, trivially handle lists of all possible sizes.