How to abstract from data type parameters in class instances?

Viewed 116

As a toy project, I would like to understand how to model mathematical groups in Haskell in general.

To start us off, we begin by observing that a to be defined Group is just a Monoid with inversion.

class (Monoid m) => Group m where
    minvert :: m -> m

Next, we first restrict ourselves to cyclic groups and start by defining the cyclic group of order 12.

data Cyclic12 = Cyclic12 Int deriving (Show, Eq)

Finally, we instantiate both classes for Cyclic12.

instance Monoid Cyclic12 where
    mempty = Cyclic12 0
    mappend (Cyclic12 x) (Cyclic12 y) = Cyclic12 ((x + y) `mod` 12)

instance Group Cyclic12 where
    minvert (Cyclic12 x) = Cyclic12 ((0 - x) `mod` 12)

How do I abstract the previous definition from the specific value of 12 to allow a more generic definition of different cyclic groups?

Ideally, I would like to write definitions like

instance Monoid (Cyclic k) where
    mempty = Cyclic k 0
    mappend (Cyclic k x) (Cyclic k y) = Cyclic k ((x + y) `mod` k)

instance Group (Cyclic k) where
    minvert (Cyclic k x) = Cyclic k ((0 - x) `mod` k)

But with a data definition like

data Cyclic = Cyclic Int Int deriving (Show, Eq)

we still don't get very far, because k is "not in scope". Regarding its apparent triviality I have a feeling to be missing out on some fundamental concept here. Thanks in advance for your help.

1 Answers
Related