简体   繁体   English

将模块恢复为记录

[英]Reify a module into a record

Suppose I have an arbitrary module 假设我有一个任意模块

module Foo where
foo :: Moo -> Goo
bar :: Car -> Far
baz :: Can -> Haz

where foo , bar , and baz are correctly implemented, etc. foobarbaz正确实现的地方等。

I'd like to reify this module into an automatically-generated data type and corresponding object: 我想将此模块重新生成为自动生成的数据类型和相应的对象:

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
  }

Names must be precisely the same as the original module. 名称必须与原始模块完全相同。

I could do this by hand, but that is very tedious, so I'd like to write some code to perform this task for me. 我可以手动执行此操作,但这非常繁琐,所以我想编写一些代码来为我执行此任务。

I'm not really sure how to approach such a task. 我不确定如何处理这样的任务。 Does Template Haskell provide a way to inspect modules? Template Haskell是否提供了检查模块的方法? Should I hook into some GHC api? 我应该加入一些GHC api吗? Or am I just as well off with a more ad-hoc approach such as scraping haddock pages? 或者我还有一个更特别的方法,如刮黑线鳕页?

(This is for GHC-7.4.2; it probably won't compile with HEAD or 7.6 because of some changes in Outputable ). (这适用于GHC-7.4.2;由于Outputable的一些变化,它可能无法使用HEAD或7.6进行Outputable )。 I didn't find anything to inspect modules in TH. 我没有找到任何东西来检查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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM