I have very innocent-looking code
data Config = Config
{ cInts :: [Int]
, cStrings :: [String] }
instance Semigroup Config where
c1 <> c2 = Config
{ cInts = andCombiner cInts
, cStrings = andCombiner cStrings }
where
andCombiner field = field c1 <> field c2
It compiles and works fine. However if I add TypeFamilies
or GADTs
extension I see very strange error:
.../Main.hs:19:22: error:
• Couldn't match type ‘Int’ with ‘[Char]’
Expected type: [String]
Actual type: [Int]
• In the ‘cStrings’ field of a record
In the expression:
Config {cInts = andCombiner cInts, cStrings = andCombiner cStrings}
In an equation for ‘<>’:
c1 <> c2
= Config
{cInts = andCombiner cInts, cStrings = andCombiner cStrings}
where
andCombiner field = field c1 <> field c2
|
19 | , cStrings = andCombiner cStrings }
| ^^^^^^^^^^^^^^^^^^^^
.../Main.hs:19:34: error:
• Couldn't match type ‘[Char]’ with ‘Int’
Expected type: Config -> [Int]
Actual type: Config -> [String]
• In the first argument of ‘andCombiner’, namely ‘cStrings’
In the ‘cStrings’ field of a record
In the expression:
Config {cInts = andCombiner cInts, cStrings = andCombiner cStrings}
|
19 | , cStrings = andCombiner cStrings }
| ^^^^^^^^
What can be the reason for this compiler error?
This is due to -XMonoLocalBinds
which -XGADTs
and -XTypeFamilies
imply. You can get your code to compile again by adding a type signature to andCombiner
(or by turning on -XNoMonoLocalBinds
, although I do not recommend that):
instance Semigroup Config where
c1 <> c2 = Config
{ cInts = andCombiner cInts
, cStrings = andCombiner cStrings }
where
andCombiner :: Semigroup a => (Config -> a) -> a
andCombiner field = field c1 <> field c2
Using the terminology from the GHC docs I've linked, andCombiner
is not fully generalized because it mentions c1
and c2
which are not closed or imported.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With