繁体   English   中英

有没有办法如何使用Template Haskell枚举模块中的所有函数?

[英]Is there a way how to enumerate all functions in a module using Template Haskell?

虽然我可以使用reify来获取有关大多数其他语法结构的信息,但我找不到任何可以提供有关模块的信息的内容。

不幸的是,模板Haskell目前没有这样的功能。 所有解决方案都涉及解析模块的源代码。 但是,TH的locationloc_filename函数可以很容易地使用调用splice定位模块。

这是从我的一个项目的源代码中提取的解决方案:

{-# LANGUAGE LambdaCase, TupleSections #-}
import Language.Haskell.TH
import qualified Data.Attoparsec.Text as AP
import qualified Data.Text.IO as Text
import qualified Data.Text as Text
import qualified Data.Char as Char
import Data.Maybe
import Data.List
import Control.Applicative
import Data.Traversable
import Prelude hiding (mapM)


reifyLocalFunctions :: Q [(Name, Type)]
reifyLocalFunctions =
  listTopLevelFunctionLikeNames >>=
  mapM (\name -> reifyFunction name >>= mapM (return . (name, ))) >>=
  return . catMaybes
  where
    listTopLevelFunctionLikeNames = do 
      loc <- location
      text <- runIO $ Text.readFile $ loc_filename loc
      return $ map (mkName . Text.unpack) $ nub $ parse text
      where
        parse text = 
          either (error . ("Local function name parsing failure: " ++)) id $
          AP.parseOnly parser text
          where
            parser = 
              AP.sepBy (optional topLevelFunctionP <* AP.skipWhile (not . AP.isEndOfLine)) 
                       AP.endOfLine >>=
              return . catMaybes
              where
                topLevelFunctionP = do
                  head <- AP.satisfy Char.isLower
                  tail <- many (AP.satisfy (\c -> Char.isAlphaNum c || c `elem` ['_', '\'']))
                  return $ Text.pack $ head : tail

reifyFunction :: Name -> Q (Maybe Type)
reifyFunction name = do
  tryToReify name >>= \case
    Just (VarI _ t _ _) -> return $ Just $ t
    _ -> return Nothing

tryToReify :: Name -> Q (Maybe Info)
tryToReify n = recover (return Nothing) (fmap Just $ reify n) 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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