I want to create several incompatible but otherwise equal data types. That is, I would like to have a parameterized type Foo a , and functions such as
bar :: (Foo a) -> (Foo a) -> (Foo a)
not caring about what a . To clarify further, I would like the type system to stop me from doing
x :: Foo Int y :: Foo Char bar xy
while I at the same time do not care about Int and Char (I do not care that they do not match).
In my actual code, I have a type for polynomials over a given ring. I donβt care what is indefinite, until the type system prevents me from adding a polynomial in t with polynomial in s. So far I have solved this by creating typeclass Indeterminate and parameterizing my polynomial type as
data (Ring a, Indeterminate b) => Polynomial ab
This approach seems completely natural for the Ring part, because I care about which particular ring is given for the polynomial. It feels very far-fetched for the Indeterminate part, as described below.
This approach works great, but feels far-fetched. Moreover, this part:
class Indeterminate a where indeterminate :: a data T = T instance Indeterminate T where indeterminate = T data S = S instance Indeterminate S where indeterminate = S
(and so on, perhaps a few more uncertainties). This is strange and wrong. Essentially, I'm trying to require Indeterminate instances to be single (for that matter). A sense of strangeness is one of the indicators that I may be wrong in this. Another is the fact that I end up having to comment on a lot of my Polynomial ab , since the actual type b often cannot be inferred (which is not strange, but annoying anyway).
Any suggestions? Should I continue to do it this way, or am I missing something?
PS: Do not be offended if I do not immediately respond or accept the answers. I will not be able to return for a few days.