这就是所谓的higher-order abstract syntax。
第一个解决方案:使用Haskell的lambda。 一个数据类型可以是这样的:
ForAll (\x -> Exists (\y -> Equals (Add x y) (Mul x y))))
对此进行了详细在The Monad Reader文章描述:
data Prop
= Not Prop
| And Prop Prop
| Or Prop Prop
| Impl Prop Prop
| Equiv Prop Prop
| Equals Obj Obj
| ForAll (Obj -> Prop)
| Exists (Obj -> Prop)
deriving (Eq, Ord)
data Obj
= Num Integer
| Add Obj Obj
| Mul Obj Obj
deriving (Eq, Ord)
,你可以写一个公式。强烈推荐。
解决方法二:
使用字符串像
data Prop
= Not Prop
| And Prop Prop
| Or Prop Prop
| Impl Prop Prop
| Equiv Prop Prop
| Equals Obj Obj
| ForAll String Prop
| Exists String Prop
deriving (Eq, Ord)
data Obj
= Num Integer
| Var String
| Add Obj Obj
| Mul Obj Obj
deriving (Eq, Ord)
然后,你可以这样写
ForAll "x" (Exists "y" (Equals (Add (Var "x") (Var "y")))
(Mul (Var "x") (Var "y"))))))
优势的公式是,你可以很容易地显示公式(很难显示Obj -> Prop
函数)。缺点是您必须在碰撞(〜alpha转换)和替换(〜beta转换)时编写更改的名称。在两种方案中,可以使用GADT,而不是两个数据类型:
data FOL a where
True :: FOL Bool
False :: FOL Bool
Not :: FOL Bool -> FOL Bool
And :: FOL Bool -> FOL Bool -> FOL Bool
...
-- first solution
Exists :: (FOL Integer -> FOL Bool) -> FOL Bool
ForAll :: (FOL Integer -> FOL Bool) -> FOL Bool
-- second solution
Exists :: String -> FOL Bool -> FOL Bool
ForAll :: String -> FOL Bool -> FOL Bool
Var :: String -> FOL Integer
-- operations in the universe
Num :: Integer -> FOL Integer
Add :: FOL Integer -> FOL Integer -> FOL Integer
...
解决方案三:用数字来表示,其中的变量绑定,其中较低的手段更深。例如,在ForAll(Exists(Equals(Num 0)(Num 1)))中,第一个变量将绑定到Exists,第二个绑定到ForAll。这被称为de Bruijn数字。见I am not a number - I am a free variable。
我想我有一些阅读做..谢谢!我在完成文章后会回到这里。 – wen 2010-07-12 15:27:15
只是挑剔,但它仍然是阿尔法转换,即使它发生在替代时间。 – finrod 2010-07-12 21:52:10
我认为术语“高阶抽象语法”仅适用于第一种解决方案。你的答案似乎是说问题本身(或所有三种解决方案)被称为HOAS。 – 2010-07-12 22:53:35