我發現自己一遍又一遍地重複一個模式,我想抽象它。我相當有信心coq足夠表達捕捉模式,但我在設法解決這個問題時遇到了一些麻煩。我定義編程語言,它具有代表句法方面相互遞歸感應數據類型:coq中的歸納數據類型的通用摺疊
Inductive Expr : Set :=
| eLambda (x:TermVar) (e:Expr)
| eVar (x:TermVar)
| eAscribe (e:Expr) (t:IFType)
| ePlus (e1:Expr) (e2:Expr)
| ... many other forms ...
with DType : Set :=
| tArrow (x:TermVar) (t:DType) (c:Constraint) (t':DType)
| tInt
| ... many other forms ...
with Constraint : Set :=
| cEq (e1:Expr) (e2:Expr)
| ...
現在,有一些的,我需要定義在這些類型的功能。例如,我想要一個函數來查找所有的自由變量,一個執行替換的函數,以及一個抽取所有約束集合的函數。這些功能都具有以下形式:
Fixpoint doExpr (e:Expr) := match e with
(* one or two Interesting cases *)
| ...
(* lots and lots of boring cases,
** all of which just recurse on the subterms
** and then combine the results in the same way
*)
| ....
with doIFType (t:IFType) := match t with
(* same structure as above *)
with doConstraint (c:Constraint) := match c with
(* ditto *)
例如,要查找免費的變量,我需要做的事情在變量的情況下,並且做結合的情況下有趣的,但一切我只是遞歸找到所有的子表達式的自由變量,然後將這些列表結合在一起。對於生成所有約束列表的函數也是如此。替代的情況下是更加棘手一點點,因爲結果類型的三個功能是不同的,以及用於將子表達式組合構造也不同:
Variable x:TermVar, v:Expr.
Fixpoint substInExpr (e:Expr) : **Expr** := match e with
(* interesting cases *)
| eLambda y e' =>
if x = y then eLambda y e' else eLambda y (substInExpr e')
| eVar y =>
if x = y then v else y
(* boring cases *)
| eAscribe e' t => **eAscribe** (substInExpr e') (substInType t)
| ePlus e1 e2 => **ePlus** (substInExpr e1) (substInExpr e2)
| ...
with substInType (t:Type) : **Type** := match t with ...
with substInConstraint (c:Constraint) : **Constraint** := ...
.
編寫這些功能是乏味的且容易出錯的,因爲我必須爲每個函數寫出所有不感興趣的案例,並且我需要確保對所有子項遞歸。我想寫的是像下面這樣:
Fixpoint freeVars X:syntax := match X with
| syntaxExpr eVar x => [x]
| syntaxExpr eLambda x e => remove x (freeVars e)
| syntaxType tArrow x t1 c t2 => remove x (freeVars t1)++(freeVars c)++(freeVars t2)
| _ _ args => fold (++) (map freeVars args)
end.
Variable x:TermVar, v:Expr.
Fixpoint subst X:syntax := match X with
| syntaxExpr eVar y => if y = x then v else eVar y
| syntaxExpr eLambda y e => eLambda y (if y = x then e else (subst e))
| syntaxType tArrow ...
| _ cons args => cons (map subst args)
end.
這種想法的關鍵是構造一般適用於一些數量的參數,並且有某種的「地圖」,即,保留的能力參數的類型和數量。
很明顯,這個僞碼不起作用,因爲_ cases只是不正確。所以我的問題是,是否有可能編寫以這種方式組織的代碼,或者我註定要手動列出所有無聊的情況?
這似乎是相關的,雖然我沒有經歷過它的工作又那麼不能從經驗談:http://adam.chlipala.net/cpdt/html/Generic.html – t0yv0 2013-03-03 20:59:45
文件是自動生成的,但你可以在這裏看到定義:http://dl.dropbox.com/u/3989078/aflang.v。我的問題改變了名字,以保護無辜 - DType是文件中的IFType。 – mdgeorge 2013-03-04 19:14:25