Asking ghci
about instances of a record type R
does not return the instances of HasField
.
data R = MkR {f1 :: Int, f2 :: Int}
instance HasField "f3" R Int where
getField (MkR a b) = a + b
-- ghci
>:i R
type R :: *
data R = MkR {f1 :: Int, f2 :: Int}
-- I'd expect instances for HasField <f1 | f2 | f3>
-- But they aren't in the output
I assume is due to the multiparam nature of such a class, so I tried to write a template haskell snnipet following this other SO answer. The thing is that I am unable to make it work... It just return the empty list.
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DataKinds #-}
import Language.Haskell.TH
( stringL,
Exp(LitE),
Q,
Type(ConT),
Name,
InstanceDec,
reifyInstances )
import GHC.Records (HasField (getField))
getFieldIntances :: Name -> Q [InstanceDec]
getFieldIntances name = reifyInstances ''HasField [ConT name] -- Is this even correct?? I guess ConT is the constructor for "type constructors"
showFieldInstances :: Name -> Q Exp
showFieldInstances name = LitE . stringL . show <$> getFieldIntances name
data R = MkR {f1 :: Int, f2 :: Int}
instance HasField "f3" R Int where
getField (MkR a b) = a + b
-- If hls eval pluging is activated
-- >>> $(showFieldInstances ''R)
-- "[]"
I have zero knowledge of template haskell. Is there any way to do this?
Thanks in advance
EDIT
I have an ilumination that reifyInstances
only works for "fully applied" type classes, so I modify:
getFieldIntances :: Name -> Q [InstanceDec]
getFieldIntances name = reifyInstances ''HasField [ VarT ( mkName "a") , ConT name, VarT ( mkName "b")]
-- ...
-- >>> $(showFieldInstances ''R)
-- "[InstanceD Nothing [] (AppT (AppT (AppT (ConT GHC.Records.HasField) (LitT (StrTyLit \"f3\"))) (ConT Main.R)) (ConT GHC.Types.Int)) []]"
Which kind of works, but only for explicit instances (virtual fields). can I get ghc generated ones?