Haskell's traditional data is just that: data. He should not know anything about the properties of his fields, he simply should be able to store them. Therefore, there is no real need to limit the fields at this point; just do it
data Complex a = Complex !a !a
( ! because strict margins are better for performance).
Of course, when you implement an instance of Num , you will need a restriction:
instance (Num a) => Num (Complex a) where fromInteger = (`Complex`0) . fromInteger Complex ri + Complex ฯ ฮน = Complex (r+ฯ) (i+ฮน) ...
... in fact, you need a much stronger restriction on RealFloat a implement abs , at least that the standard version does this . (This means that Complex Int is not actually used, not the standard Num hierarchy; you need, for example, Complex Double .)
However, it is also possible to bake a restriction on the data type itself. The ExistentialTypes syntax you tried is very limited, although not suitable for this; instead you want a gadt
data Complex a where Complex :: Num a => a -> a -> Complex a
Using this, you could implement, for example. add without mentioning any signature restrictions
cplxAdd :: Complex a -> Complex a -> Complex a cplxAdd (Complex ri) (Complex ฯ ฮน) = Complex (r+ฯ) (i+ฮน)
Now you need to execute Num when you try to build the value of Complex . This means that you still need an explicit restriction on the Num instance.
Also, this version is potentially much slower, because the Num dictionary really needs to be stored in the runtime view.
leftaroundabout
source share