2

I'm writing some parser code, which involves a parameterized type:

data Power i    = Power1 { charges :: i } | Power2 { charges :: i }

Where I know the type i will always be an Int (but is parameterized because I need it for another type class).
Now I want to make my Power type derive from Show (in a specific formatting, so I need to override it myself). As I know that i will only ever be Int, I tried:

instance Show (Power Int) where
    show (Power1 0)    = ""
    show (Power1 i)    = "some formatting involving i\n"
    show (Power2 0)    = ""
    show (Power2 i)    = "some other formatting involving i\n"

However, this won't compile, with the message

    • Illegal instance declaration for ‘Show (Power Int)’
        (All instance types must be of the form (T a1 ... an)
         where a1 ... an are *distinct type variables*,
         and each type variable appears at most once in the instance head.
         Use FlexibleInstances if you want to disable this.)
    • In the instance declaration for ‘Show (Power Int)’
   |
22 | instance Show (Power Int) where

Why isn't this possible?

Why is this so different to the compiler than?

instance (Show i) => Show (Power i) where

2 Answers 2

3

GHC says All instance types must be of the form (T a1 ... an) where a1 ... an are *distinct type variables*. That is defined in Haskell 98. To take data type with a concrete type as class parameter require FlexibleInstances extension. Because there is overwrapping instances problem.

For example:

newtype Foo a = Foo a

class Bar a where
    baz :: a -> a

instance Bar (Foo Int) where
    baz = ...

instance Show a => Bar (Foo a) where
    baz = ...

When you call baz 1, compiler confuses whether version should call. 1 is Int but also belongs Show class! Details written in this post, you should read it when you have time.

Sign up to request clarification or add additional context in comments.

Comments

1

You can not use type constraints with Types, but with Type classes. In your example, it is possible to instantiate Show for the Integral type class. Then show is defined for Power Int and Power Integer.

instance Integral a => Show (Power a) where
    show (Power1 0)    = ""
    show (Power1 i)    = "some formatting involving i\n"
    show (Power2 0)    = ""
    show (Power2 i)    = "some other formatting involving i\n"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.