
On 2006-09-12, Brian Hulley
Bryan Burgers wrote:
That being said, I'll have to play the other side of the coin: it would probably be a little bit of a pain to have to define instances of each data declaration (Integer, Int, Float, Matrix, Complex, etc.) on each of these seperate classes--especially when being in a certain class usually implies being in another (ie, the definition of a set being a field requires that that set is a group, right?)
Aaron Denney wrote:
On 2006-09-12, Bryan Burgers
wrote: And another problem I can see is that, for example, the Integers are a group over addition, and also a group over multiplication;
Not over multiplication, no, because there is no inverse.
I know of no good way to express that a given data type obeys the same interface two (or more) ways. Some OO languages try to handle the case of of an abstract base class being inherited twice through two different intermediate classes, but none of them do it well.
How about:
data Multiply = Multiply data Add = Add
class Group c e where group :: c -> e -> e -> e identity :: c -> e inverse :: c -> e -> e
instance Group Multiply Rational where group Multiply x y = ... identity Multiply = 1 inverse Multiply x = ...
instance Group Add Rational where group Add x y = ... identity Add = 0 inverse Add x = ...
(+) :: Group Add a => a -> a -> a (+) = group Add
(*) = group Multiply
class (Group Multiply a, Group Add a) => Field a where ...
It's not horrible, but it's somewhat cumbersome, much like passing around dictionaries explicitly is. -- Aaron Denney -><-