Skip to content

Instantly share code, notes, and snippets.

@s9gf4ult
Last active July 25, 2018 15:45
Show Gist options
  • Save s9gf4ult/f75b77a92cbc1677887a0547bf564e4e to your computer and use it in GitHub Desktop.
Save s9gf4ult/f75b77a92cbc1677887a0547bf564e4e to your computer and use it in GitHub Desktop.
module A
makeEtherHasLens :: Name -> DecsQ
makeEtherHasLens name = do
TyConI dec <- reify name
fields <- case dec of
DataD _ctx _name _tvars _kind [dataCon] _derive -> case dataCon of
RecC _conName fs -> return $ (\(n, _bang, ty) -> (n, ty)) <$> fs
_ -> fail $ show name ++ ": hust have prefix constructor with named fields"
_ -> fail $ show name ++ ": must be one constructor record with named fields"
genHasLens (VarT name) fields
genHasLens
:: Type
-- ^ Struct type
-> [(Name, Type)]
-- ^ Fields of struct
-> DecsQ
genHasLens outer fields = fmap mconcat $ for fields $ \(nm, typ) -> do
let
setLens = do
s <- newName "s"
a <- newName "a"
let upd = RecUpdE (VarE s) [(nm, VarE a)]
[e| ( \ $(varP s) $(varP a) -> $(pure upd) ) |]
[d|instance E.HasLens $(pure typ) $(pure outer) $(pure typ) where
lensOf = lens $(varE nm) $(setLens)|]
module B
import A
data Rec = Rec
{ _rInt :: Int
, _rString :: String
}
makeEtherHasLens ''Rec
@s9gf4ult
Copy link
Author

Illegal type variable name: ‘Rec’
When splicing a TH declaration:
  instance Ether.Internal.HasLens.HasLens GHC.Types.Int
                                    EtherCompat.Rec
                                    GHC.Types.Int
where Ether.Internal.HasLens.lensOf = Control.Lens.Lens.lens EtherCompat._rInt (\s_0 a_1 -> s_0{EtherCompat._rInt = a_1})

|
40 | makeEtherHasLens ''Rec
| ^^^^^^^^^^^^^^^^^^^^^^
Progress 1/2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment