I am trying to imagine expressions with type families, but I cannot figure out how to write the constraints that I want, and I am starting to feel that this is simply not possible. Here is my code:
class Evaluable c where type Return c :: * evaluate :: c -> Return c data Negate n = Negate n instance (Evaluable n, Return n ~ Int) => Evaluable (Negate n) where type Return (Negate n) = Return n evaluate (Negate n) = negate (evaluate n)
All of this compiles fine, but it does not express exactly what I want. In the limitations of the Negate Evaluable I say that the return type of the expression inside Negate must be Int (with Return n ~ Int ), so I can call it negation, but this is too restrictive. The return type should actually be an instance of a class of type Num that has a Negate function. Thus, Double s, Integer s, or any other Num instance could also be undone, not just Int s. But I canβt just write
Return n ~ Num
because Num is a type class, and Return n is a type. I also can not put
Num (Return n)
because Return n is a type, not a type variable.
Am I trying to do this with Haskell? If not, if so, or do I not understand some theory behind it? I feel that Java can add a restriction similar to this. Let me know if this question can be clearer.
Edit: Thanks guys, the answers help and get what I suspected. It seems like the type checker cannot handle what I would like to do without UndecidableInstances, so my question is what I would like to express really insoluble? This is for the Haskell compiler, but is it at all? that is, there may be a constraint that means "check that Return n is an instance of Num" that is solvable for a more advanced type of check?
haskell typeclass type-constraints type-families type-level-computation
user3773003
source share