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?