2017-12-29 161 views
7

mam bardzo niewinnie wyglądający kodTypeFamilies lub GADTs nagle przerywa poprawny kod

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 

To kompiluje i działa poprawnie. Jednak jeśli dodam TypeFamilies lub GADTs przedłużenie widzę bardzo dziwny błąd:

.../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 } 
    |         ^^^^^^^^ 

Co może być przyczyną tego błędu kompilatora?

Odpowiedz

10

Jest to spowodowane -XMonoLocalBinds, które oznaczają: -XGADTs i -XTypeFamilies. Możesz otrzymać kod skompilować ponownie poprzez dodanie podpisu do andCombiner typu (lub przez włączenie -XNoMonoLocalBinds, choć robię nie zalecają):

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 

Używając terminologii z docs GHC Mam powiązanych , andCombiner nie jest w pełni uogólniony, ponieważ wspomina o c1 i c2, które nie są zamknięte ani zaimportowane.

+4

Czy chodzi o wyłączenie '-XMonoLocalBinds' * off *, z' -XNoMonoLocalBinds'? – HTNW

+0

@HTNW Tak, dziękuję bardzo! – Alec