Dan*_*ton 10 haskell module ghc-api template-haskell
假设我有一个任意模块
module Foo where
foo :: Moo -> Goo
bar :: Car -> Far
baz :: Can -> Haz
Run Code Online (Sandbox Code Playgroud)
在哪里foo,bar和baz,正确实施等
我想将此模块重新生成为自动生成的数据类型和相应的对象:
import Foo (Moo, Goo, Car, Far, Can, Haz)
import qualified Foo
data FooModule = Foo
{ foo :: Moo -> Goo
, bar :: Car -> Far
, baz :: Can -> Haz
}
_Foo_ = Foo
{ foo = Foo.foo
, bar = Foo.bar
, baz = Foo.baz
}
Run Code Online (Sandbox Code Playgroud)
名称必须与原始模块完全相同.
我可以手动执行此操作,但这非常繁琐,所以我想编写一些代码来为我执行此任务.
我不确定如何处理这样的任务.Template Haskell是否提供了检查模块的方法?我应该加入一些GHC api吗?或者我还有一个更特别的方法,如刮黑线鳕页?
(这是针对 GHC-7.4.2 的;由于 中的一些更改,它可能无法使用 HEAD 或 7.6 进行编译Outputable)。我在 TH 中没有找到任何可以检查模块的内容。
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# OPTIONS -Wall #-}
import GHC
import GHC.Paths -- ghc-paths package
import Outputable
import GhcMonad
main :: IO ()
main = runGhc (Just libdir) $ goModule "Data.Map"
goModule :: GhcMonad m => String -> m ()
goModule modStr = do
df <- getSessionDynFlags
_ <- setSessionDynFlags df
-- ^ Don't know if this is the correct way, but it works for this purpose
setContext [IIDecl (simpleImportDecl (mkModuleName modStr))]
infos <- mapM getInfo =<< getNamesInScope
let ids = onlyIDs infos
liftIO . putStrLn . showSDoc . render $ ids
onlyIDs :: [Maybe (TyThing, Fixity, [Instance])] -> [Id]
onlyIDs infos = [ i | Just (AnId i, _, _) <- infos ]
render :: [Id] -> SDoc
render ids = mkFields ids $$ text "------------" $$ mkInits ids
mkFields :: [Id] -> SDoc
mkFields = vcat . map (\i ->
text "," <+> pprUnqual i <+> text "::" <+> ppr (idType i))
mkInits :: [Id] -> SDoc
mkInits = vcat . map (\i ->
text "," <+> pprUnqual i <+> text "=" <+> ppr i)
-- * Helpers
withUnqual :: SDoc -> SDoc
withUnqual = withPprStyle (mkUserStyle neverQualify AllTheWay)
pprUnqual :: Outputable a => a -> SDoc
pprUnqual = withUnqual . ppr
Run Code Online (Sandbox Code Playgroud)