給定一個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