[英]Reify a module into a record
假設我有一個任意模塊
module Foo where
foo :: Moo -> Goo
bar :: Car -> Far
baz :: Can -> Haz
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
}
名稱必須與原始模塊完全相同。
我可以手動執行此操作,但這非常繁瑣,所以我想編寫一些代碼來為我執行此任務。
我不確定如何處理這樣的任務。 Template Haskell是否提供了檢查模塊的方法? 我應該加入一些GHC api嗎? 或者我還有一個更特別的方法,如刮黑線鱈頁?
(這適用於GHC-7.4.2;由於Outputable
的一些變化,它可能無法使用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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.