7
votes

I stumbled upon the following small problem. I am using Haskell record syntax, together with GADTs:

{-# LANGUAGE GADTs #-}

data Test a where 
  Test :: {someString :: String, someData :: a} -> Test a

Now I want to create a new Test value with a different type for someData, but the same value for someString (to justify the usage of the record update syntax):

test :: Test a -> Test Bool
test t = t {someData = True}

Suppose I add another field to the Test constructor:

data Test a where 
  Test :: {someString :: String, someData :: a, someMoreData :: a} -> Test a

Then I have to change both fields to keep my code type-correct:

test :: Test a -> Test Bool
test t = t {someData = True, someMoreData = False}

Until now, I didn't need the GADT, but now I want to add a type-class constraint to the data type, for example Eq:

data Test a where 
  Test :: Eq a => {someString :: String, someData :: a} -> Test a

When trying to "update" the someData field, like in the first example, I suddenly get a compiler error:

Couldn't match type ‘a’ with ‘Bool’
  ‘a’ is a rigid type variable bound by
      the type signature for test :: Test a -> Test Bool at Test.hs:18:9
Expected type: Test Bool
  Actual type: Test a
Relevant bindings include
  t :: Test a (bound at Test.hs:19:6)
  test :: Test a -> Test Bool (bound at Test.hs:19:1)
In the expression: t
In the expression: t {someData = True}

I suspect this to be the same "problem" as in the case before with two fields of type a, but a little more implicit. I guess the dictionary for the Eq type class is treated like an argument of the constructor, just like if I had a field {eqDict :: Eq a}. If I am right, then I also had to "update" the "dictionary field" somehow, although I don't know how to do this. The question is, is there a way to use record update syntax when type classes are involved like this?

1

1 Answers

5
votes