在编译之前向Haskell函数添加额外的参数

时间:2013-01-23 23:23:43

标签: parsing haskell preprocessor metaprogramming

作为将用户输入的字符串动态加载为Haskell源代码的程序的一部分,我想在编译之前对用户的输入进行一些预处理。

我希望能够做的事情之一是搜索特定功能事件的源并为它们添加额外的参数。因此,例如,我可能想要出现所有:

addThreeNumbers 3 5

成为:

addThreeNumbers 3 5 10

完成此类行为的最佳方法是什么?它是否足够复杂以保证在GHC API / Template Haskell中使用函数操作某种抽象语法树?或者这是否可以通过某种Haskell预处理/解析库来实现?如果是这样,你会推荐哪些图书馆和资源?

1 个答案:

答案 0 :(得分:1)

Ghc 7.6 qualified imports,ghc-pkg hide和ghc的-package选项允许您在导入文件和导入文件之间无缝添加图层。

示例:

使用您自己的Data.Char创建一个包,标准的.cabal文件和cabal安装。

{-# language PackageImports #-}                                                  

module Data.Char (                                                               
      toUpper                                                                    
    , Char                                                                       

    , String                                                                     
    -- ...  Export every else from "Base" Data char because the limitation of
    --     the current export facility you can not use
    --     module Data.Char hiding (toUpper)
    ) where                                                                      

import "base" Data.Char hiding (toUpper)                                         
import qualified "base" Data.Char as OldChar                                     

toUpper :: Char -> IO Char                                                       
toUpper c = do                                                                   
    print "Oh Yeahhhhhhhhh"                                                      
    return $ OldChar.toUpper c

隐藏基础包ghc-pkg hide base - 在这种情况下隐藏了许多模块,如果需要,您需要将所有模块包装起来。

> ghci -XNoImplicitPrelude --  We need language flag because the Prelude is in
                           -- base and I did not make a wrapped Prelude
ghci> import Data.Char
ghci> toUpper 'c'  -- The wrapped function
"Oh Yeahhhhhhhhh"
'C'
ghci> isSpace ' '  -- The unwrapped normal Data.Char function
True

现在,您可以使用模板Haskell来包装您的函数并调用获取外部信息所需的任何IO操作。用户甚至不需要更改任何函数调用或模块导入,只需在其名称中添加“internal”即可。

能够无缝地包装模块接口也意味着您可以更改导入模块的植入,而无需触及包/模块代码或您正在使用的现有代码库;你只需要做一个中间层。

编辑对问题的回复:

当然你可以让ghc-api让你做到这一切,但是要复杂得多,我希望有更少的例子漂浮在周围,我似乎看到更多的人在成功故事中遇到困难。< / p>

  • 用于评估代码hint
  • pluggins建议动态加载模块
  • haskell-src-ext建议用于解析和更改代码。这是stylish-haskell用来对代码进行小修改的最佳选择。据报道它涵盖了Haskell 2010的大部分(全部?),以及许多但不是所有的GHC扩展,如果你不喜欢我提供的第一个解决方案,这可能是你最好的选择。

据我所知,GHC-API是唯一一个与GHC兼容代码完全兼容的API,但它相当复杂,文档记录较少,更有可能从GHC版本更改为GHC版本,或者至少没有从我有限的经验来看,它会是一样的。我建议在中间放置一个模块,因为看起来最快的是获得良好的测试覆盖率,获取最少的新知识并满足我从你的问题中挑选出来的要求。