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

Parsing 在编译前向Haskell函数添加额外参数,parsing,haskell,preprocessor,metaprogramming,Parsing,Haskell,Preprocessor,Metaprogramming,作为动态加载用户输入字符串作为Haskell源代码的程序的一部分,我想在编译用户输入之前对其进行一些预处理 我希望能够做的一件事是搜索源代码中的特定函数实例,并为它们添加一个额外的参数。例如,我可能希望出现以下所有情况: addThreeNumbers 3 5 成为: addThreeNumbers 3 5 10 实现这种行为的最佳方式是什么?在GHCAPI/模板Haskell中使用函数操作某种抽象语法树是否足够复杂?或者这是一件简单的事情,可以通过某种Haskell预处理/解析库来完成吗?

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

我希望能够做的一件事是搜索源代码中的特定函数实例,并为它们添加一个额外的参数。例如,我可能希望出现以下所有情况:

addThreeNumbers 3 5
成为:

addThreeNumbers 3 5 10
实现这种行为的最佳方式是什么?在GHCAPI/模板Haskell中使用函数操作某种抽象语法树是否足够复杂?或者这是一件简单的事情,可以通过某种Haskell预处理/解析库来完成吗?如果是这样,您会推荐哪些库和资源?

Ghc 7.6、Ghc pkg hide和Ghc的-package选项允许您在导入文件和导入文件之间无缝添加一层

例如:

使用您自己的Data.Char、standard.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
现在,您可以使用TemplateHaskell包装您的函数,并调用您需要的任何IO操作来获取外部信息。用户甚至不需要更改任何函数调用或模块导入,只需在名称中添加“internal”即可

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

编辑对问题的答复:

当然可以,ghc api可以让您完成所有这一切,但它要复杂得多,我希望的例子更少,我似乎看到更多的人在使用它时遇到困难,然后是成功的故事

  • 用于代码的评估
  • 建议对模块进行动态加载
  • haskell src ext建议解析和更改代码。这是用来对代码进行小修改的,是您最好的选择。据报道,它涵盖了Haskell 2010的大部分(全部?),以及许多但不是全部GHC扩展,如果您不喜欢我提供的第一个解决方案,它可能是您的最佳选择
据我所知,GHC-API是唯一一个与GHC兼容的代码完全兼容的API,但它要复杂得多,文档较少,并且更可能从GHC版本更改为GHC版本,或者从我有限的经验来看,至少没有承诺它会是相同的。我建议把一个模块放在中间,因为它似乎是最快的工作与良好的测试覆盖率,采取最少的新知识,并满足我的要求,我挑选出你的问题。< / P > P>GHC 7.6,GHC PKG隐藏,ghc的-package选项允许您在导入文件和导入文件之间无缝添加一层

例如:

使用您自己的Data.Char、standard.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
现在,您可以使用TemplateHaskell包装您的函数,并调用您需要的任何IO操作来获取外部信息。用户甚至不需要更改任何函数调用或模块导入,只需在名称中添加“internal”即可

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

编辑对问题的答复:

当然可以,ghc api可以让您完成所有这一切,但它要复杂得多,我希望的例子更少,我似乎看到更多的人在使用它时遇到困难,然后是成功的故事

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

据我所知,GHC-API是唯一一个与GHC兼容的代码完全兼容的API,但它要复杂得多,文档较少,并且更可能从GHC版本更改为GHC版本,或者从我有限的经验来看,至少没有承诺它会是相同的。我建议把一个模块放在中间,因为它看起来是最快的,可以用很好的测试覆盖率,用最少的新知识,满足我从你的问题中挑选出来的要求。这取决于什么?类型?名字?只是给你一个最简单的开始讨论的方法。。。将代码的
addThreeNumbers
重命名为
addThreeNumbersInternal
并定义
addThreeNumbers x y=addThreeNumbersInternal x y 10
?@这完全取决于此时的名称。例如,我想说“查找所有出现的'AddThreeNumber'函数,并为它们添加一个值为10的额外参数”@Daniel Wagner这似乎确实适用于简单的情况,但我想象的情况是:1。我可能需要根据用户输入代码之外的信息(例如,外部操作的时间戳,或函数出现的行号)添加参数值2。这很容易改变。比如说,明天我决定给addThreeNumber的所有出现添加两个参数