# Declaring a "subclass" in Haskell

I am having problems with the following simple code in Haskell:

```
import Prelude hiding (cycle).
class ICycle a where
cycle :: a -> a
instance ICycle [a] where
cycle [] = []
cycle (x:xs) = xs ++ [x]
instance ICycle Bool where
cycle True = False
cycle False = True
instance Num a => ICycle a where
cycle n = n+1
main = do
print $ cycle $ [1,2,3]
print $ cycle $ True
print $ cycle $ 42
```

Here the first two instance declarations work as expected, but the third throws different kinds of errors depending on the flag combinations.

I know it is `Num a`

not shorter `ICycle a`

and hence the compiler cannot complete the type check. I've seen in the examples that this is bypassed either by the right side having a larger term, or by declaring the class of interests as a subclass of other classes. Here, on the contrary, I essentially want to declare the existing class as a subclass of the new one.

I wonder if there is any objection to this kind of use of typeclasses. Or if there is a natural solution.

source to share

For this specific example, I think you are better off using `newtype`

to wrap the instance:

```
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Prelude hiding (cycle)
class ICycle a where
cycle :: a -> a
newtype Succ a = Succ { runSucc :: a }
deriving (Num, Eq, Ord, Bounded, Enum, Show, Read)
newtype Pred a = Pred { runPred :: a }
deriving (Num, Eq, Ord, Bounded, Enum, Show, Read)
instance Enum a => ICycle (Succ a) where
cycle = Succ . succ . runSucc
instance Enum a => ICycle (Pred a) where
cycle = Pred . pred . runPred
main = do
print $ cycle $ (42 :: Succ Int)
print $ cycle $ (42 :: Pred Int)
```

There are several ways that one could cycle through the numbers - by succ, by pred, by doubling, twice. The advantage of using `newtype`

for instance (which makes RHS "bigger" as you noted in your question) is that it allows us to have ALL of them.

The standard library does the same trick with `Product`

and `Sum`

for `Monoid`

.

Look at it in a different way, if it was possible to define a new superclass for `Num`

by adding a default implementation for all instances
`Num`

, then you would take that choice away from all of those implementations. It might not make sense.

source to share

According to the Haskell 2010 report, Chapter 4, Declarations and Bindings , the subject to be defined as an instance must be a constructor type. Thus,

```
instance Num a => ICycle a where
...
```

is invalid because it `a`

is a type variable and not a type constructor.

So the valid way to do this is unfortunately by type. Need to say:

```
instance ICycle Int where
...
instance ICycle Double where
...
```

etc.

source to share