2013-05-07 34 views
4

給定一個Haskell表達式,我想執行alpha轉換,即。重命名一些非自由變量。Haskell表達式上的Alpha轉換

我已經開始實現我自己的這個功能,它在haskell-src-exts Exp樹上工作,但事實證明這是令人驚訝的不平凡,所以我不禁想知道 - 是否有一個既定的easy-這種類型的源轉換可用的庫解決方案嗎?理想情況下,它應該與haskell-src-exts集成。

+0

您可能會發現ekmett的[bound](https://github.com/ekmett/bound/)庫有幫助 – 2013-09-21 18:00:51

回答

5

這是「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或其他圖書館更平易近人。

您接近實際問題的方式將是多部分轉換,首先選擇要在其中進行阿爾法轉換的子表達式,然後使用這些轉換來修改要更改的名稱。

+2

泛型解決了一個可能的問題(使用AST)而不是另一個問題(確定alpha等價,capture-避免等)。我把這個問題解釋爲更多關於後者的問題,這裏有一些庫('unbound','bound'),但我不知道它們是否可以很容易地應用到'haskell-src-exts'。 – 2013-05-08 01:05:02

+0

+1,但是,我不確定這是我在找什麼。我不熟悉你提到的庫,但我真正想避免的不是那麼多的樣板,而是真正的邏輯(大多數情況下確定綁定名稱和自由名稱)。 – xcvii 2013-05-08 07:49:49