Compile Error Message On GHC < 8.2 and Warning on GHC 8.2
It's my first time trying generic programming forgive me if this is not accept as an issue.
I was facing an issue trying this library. I tried the code below using GHC 8.0 compiler, and I was getting the error message pasted below. I am not sure if its something that should be obvious, however, the only reference I had was the Generics.Eot.Tutorial doc on Hackage. The "The Generic instance: Don't forget!!!" section states that if one were to get the compile error message that I got below, the chances are that the user forgot to derive generic instance on their ADT. I believe that the code below follows all the requirements dictated on the Tutorial but I am was getting the same error.
With the help of a nice person on #haskell IRC, compiling the code below with GHC 8.2 only resulted in a warning message specifying how to fix the potential error.
In conclusion, I thought that it would be worth mentioning the error here.
GHC 8.0 Compile Error Message
src/Haskforce/Random.hs:22:19: error:
• Couldn't match type ‘GHC.Generics.Rep a’
with ‘GHC.Generics.M1 GHC.Generics.D c0 f0’
arising from a use of ‘namesOfFields’
The type variables ‘c0’, ‘f0’ are ambiguous
• In the expression: namesOfFields p
In a pattern binding: (f : _) = namesOfFields p
In an equation for ‘myfunc’:
myfunc p
= f
where
(f : _) = namesOfFields p
• Relevant bindings include
p :: Proxy a (bound at src/Haskforce/Random.hs:21:8)
myfunc :: Proxy a -> String (bound at src/Haskforce/Random.hs:21:1)
Failed, modules loaded: none.
GHC 8.2 Warning Error Message
src/Haskforce/Random.hs:22:18: warning: [-Wsimplifiable-class-constraints]
• The constraint ‘HasEot a’ matches an instance declaration
instance (Generic a, Generics.Eot.ImpliedByGeneric a c f) =>
HasEot a
-- Defined in ‘Generics.Eot’
This makes type inference for inner bindings fragile;
either use MonoLocalBinds, or simplify it using the instance
• In the type signature:
namesOfFields :: HasEot a => Proxy a -> [String]
|
22 | namesOfFields :: HasEot a => Proxy a -> [String]
Code
{-# LANGUAGE DeriveGeneric #-}
import qualified GHC.Generics
import Generics.Eot
import Data.Proxy
import Data.List
data Account = Account
{ id_ :: String
, name :: String }
deriving (Generic, Show)
myfunc :: HasEot a => Proxy a -> String
myfunc p = f
where (f:_) = namesOfFields p
namesOfFields :: HasEot a => Proxy a -> [String]
namesOfFields proxy =
nub $
concatMap (fieldNames . fields) $
constructors $ datatype proxy
where
fieldNames :: Fields -> [String]
fieldNames fields = case fields of
Selectors names ->
names _ -> []
Yeah, that is weird. What helps (with ghc-8.0) is to either do this:
myfunc :: HasEot a => Proxy a -> String
myfunc p = f
where
f :: String
f = head (namesOfFields p)
or use your code and enable MonoLocalBinds. The tutorial and examples now use MonoLocalBinds (since #20) so I hope that will help.
@Woody88: Now that the code examples in the tutorial have MonoLocalBinds should we still do something about this? We could mention that language extension explicitly in the The Generic instance: Don't forget!!! section.
This is a hard question. Is it something that most people that decide to tackle generic programming should understand? I have just been using Haskell for almost a year now, so I cant really answer this question.
On the other hand, if its an extension problem issue.. I don't think that everyone have knowledge of all the possible extension that GHC contains.. maybe mentioning this new found issue and solution for versions of GHC earlier than 8.2 might be a good idea since the error message isn't really helpful.
What are your thoughts?
What do you think about #22? Is that the right place to add that information, i.e. would you have found it? Does it make sense?