# Cycles in class declaration (via superclasses) sometimes make sense.

I'd like to be able to say the following, to describe the notion of an integral domain in Haskell:

```
-- | Product of non-zero elements always non-zero.
-- Every integral domain has a field of fractions.
-- The field of fractions of any field is itself.
class (Frac (Frac a) ~ Frac a, Fractional (Frac a), IntegralDomain (Frac a))
=> IntegralDomain a where
type Frac a :: *
embed :: a -> Frac a
instance IntegralDomain Integer where
type Frac Integer = Rational
embed = fromInteger
instance IntegralDomain Rational where
type Frac Rational = Rational
embed = id
```

But GHC gets scared when it sees the cyclic reference that `IntegralDomain`

instances depend on an IntegralDomain superclass, which really is cyclic in the (Frac a) case here, and that is kind of the point. =)

Right now the best approximation of the correct answer that I have for this situation is to lie and claim the constraint is weaker:

```
-- | Product of non-zero elements always non-zero
class (Frac (Frac a) ~ Frac a, Fractional (Frac a)) => AlmostIntegralDomain a where
type Frac a :: *
embed :: a -> Frac a
class (AlmostIntegralDomain a, AlmostIntegralDomain (Frac a)) => IntegralDomain a
instance (AlmostIntegralDomain a, AlmostIntegralDomain (Frac a)) => IntegralDomain a
instance AlmostIntegralDomain Integer where
type Frac Integer = Rational
embed = fromInteger
instance AlmostIntegralDomain Rational where
type Frac Rational = Rational
embed = id
```

Now the user is stuck defining a different class than the one they consume.

Alternately, with `ConstraintKinds`

, I can encode:

```
data Dict p where
Dict :: p => Dict p
class (Frac (Frac a) ~ Frac a, Fractional (Frac a)) => IntegralDomain a where
type Frac a :: *
embed :: a -> Frac a
proofFracIsIntegral :: p a -> Dict (IntegralDomain (Frac a))
default proofFracIsIntegral :: IntegralDomain (Frac a) => p a -> Dict (IntegralDomain (Frac a))
proofFracIsIntegral _ = Dict
```

but now whenever I need to get from `IntegralDomain a`

to `IntegralDomain (Frac a)`

I need to explicitly open the `proofFracIsIntegral`

with a rats' nest of `ScopedTypeVariables`

.

It would be really really nice if I could get GHC to deal with this for me as I currently have a few thousand lines of code hacking around this limitation. =/