给定一个Haskell表达式,我想执行alpha转换,即。重命名一些非自由变量。Haskell表达式上的Alpha转换
我已经开始实现我自己的这个功能,它在haskell-src-exts Exp树上工作,但事实证明这是令人惊讶的不平凡,所以我不禁想知道 - 是否有一个既定的easy-这种类型的源转换可用的库解决方案吗?理想情况下,它应该与haskell-src-exts集成。
给定一个Haskell表达式,我想执行alpha转换,即。重命名一些非自由变量。Haskell表达式上的Alpha转换
我已经开始实现我自己的这个功能,它在haskell-src-exts Exp树上工作,但事实证明这是令人惊讶的不平凡,所以我不禁想知道 - 是否有一个既定的easy-这种类型的源转换可用的库解决方案吗?理想情况下,它应该与haskell-src-exts集成。
这是“Scrap Your Boilerplate”样式泛型库闪耀的问题之一!
我最熟悉的一个是the uniplate
package,但目前我没有安装它,所以我将使用the lens
package中的(非常相似)功能。这里的想法是,它使用Data.Data.Data
(这是有史以来最合适的名字)和相关类以多态方式执行泛型操作。
这里有一个最简单的例子:
alphaConvert :: Module -> Module
alphaConvert = template %~ changeName
changeName :: Name -> Name
changeName (Ident n) = Ident $ n ++ "_conv"
changeName n = n
的(%~)
运营商与lens
,只是手段,以功能changeName
适用于一般的穿越template
选择一切。因此,它会查找每个字母数字标识符并将其附加到_conv
。因为它不本地绑定和那些在外侧范围内定义(如被导入)标识符区分
module AlphaConv where
import Language.Haskell.Exts
import Control.Lens
import Control.Lens.Plated
import Data.Data.Lens
instance Plated_conv Module_conv
main_conv
= do ParseOk_conv md_conv <- parseFile_conv "AlphaConv.hs"
putStrLn_conv $ prettyPrint_conv md_conv
let md'_conv = alphaConvert_conv md_conv
putStrLn_conv $ prettyPrint_conv md'_conv
alphaConvert_conv :: Module_conv -> Module_conv
alphaConvert_conv = template_conv %~ changeName_conv
changeName_conv :: Name_conv -> Name_conv
changeName_conv (Ident_conv n_conv)
= Ident_conv $ n_conv ++ "_conv"
changeName_conv n_conv = n_conv
不是非常有用的,但它说明的基本思想:在运行上其自己的源此程序产生这。
lens
看起来有点吓人(它有更多的功能比这更多);你可能会发现uniplate
或其他图书馆更平易近人。
您接近实际问题的方式将是多部分转换,首先选择要在其中进行阿尔法转换的子表达式,然后使用这些转换来修改要更改的名称。
泛型解决了一个可能的问题(使用AST)而不是另一个问题(确定alpha等价,capture-避免等)。我把这个问题解释为更多关于后者的问题,这里有一些库('unbound','bound'),但我不知道它们是否可以很容易地应用到'haskell-src-exts'。 – 2013-05-08 01:05:02
+1,但是,我不确定这是我在找什么。我不熟悉你提到的库,但我真正想避免的不是那么多的样板,而是真正的逻辑(大多数情况下确定绑定名称和自由名称)。 – xcvii 2013-05-08 07:49:49
您可能会发现ekmett的[bound](https://github.com/ekmett/bound/)库有帮助 – 2013-09-21 18:00:51