Haskell 中的谓词逻辑

发布于 2024-09-09 05:57:10 字数 366 浏览 5 评论 0原文

我一直在 Haskell 中使用以下数据结构来表示命题逻辑:

data Prop 
    = Pred  String
    | Not   Prop
    | And   Prop Prop
    | Or    Prop Prop
    | Impl  Prop Prop
    | Equiv Prop Prop
    deriving (Eq, Ord)

欢迎对此结构提出任何评论。

然而,现在我想扩展我的算法来处理 FOL - 谓词逻辑。 在 Haskell 中表示 FOL 的好方法是什么?

我见过的版本几乎是上述版本的扩展,以及基于更经典的上下文无关语法的版本。有没有这方面的文献可以推荐?

I've been using the following data structure for the representation of propositional logic in Haskell:

data Prop 
    = Pred  String
    | Not   Prop
    | And   Prop Prop
    | Or    Prop Prop
    | Impl  Prop Prop
    | Equiv Prop Prop
    deriving (Eq, Ord)

Any comments on this structure are welcome.

However, now I want to extend my algoritms to handle FOL - predicate logic.
What would be a good way of representing FOL in Haskell?

I've seen versions that are - pretty much - an extension of the above, and versions that are based on more classic context-free grammars. Is there any literature on this, that could be recommended?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

往昔成烟 2024-09-16 05:57:10

这称为高阶抽象语法

第一个解决方案:使用 Haskell 的 lambda。
数据类型可能如下所示:

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)

您可以将公式编写为:

ForAll (\x -> Exists (\y -> Equals (Add x y) (Mul x y))))

Monad Reader 文章。强烈推荐。

第二种解决方案:

使用像这样的字符串

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 数字。请参阅我不是号码 -我是一个自由变量

This is known as higher-order abstract syntax.

First solution: Use Haskell's lambda.
A datatype could look like:

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)

You can write a formula as:

ForAll (\x -> Exists (\y -> Equals (Add x y) (Mul x y))))

This is described in detail in in The Monad Reader article. Highly recommended.

Second solution:

Use strings like

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)

Then you can write a formula like

ForAll "x" (Exists "y" (Equals (Add (Var "x") (Var "y")))
                               (Mul (Var "x") (Var "y"))))))

The advantage is that you can show the formula easily (it's hard to show a Obj -> Prop function). The disadvantage is that you have to write changing names on collision (~alpha conversion) and substitution (~beta conversion). In both solutions, you can use GADT instead of two datatypes:

 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
    ...

Third solution: Use numerals to represent where the variable is bound, where lower means deeper. For example, in ForAll (Exists (Equals (Num 0) (Num 1))) the first variable will bind to Exists, and second to ForAll. This is known as de Bruijn numerals. See I am not a number - I am a free variable.

疑心病 2024-09-16 05:57:10

在这里添加一个答案来提及功能珍珠似乎是合适的使用循环程序进行更高的-Order Syntax,作者:Axelsson 和 Claessen,在 ICFP 2013 上发表,以及 Chiusano 在他的博客上简要描述了

该解决方案巧妙地将 Haskell 语法的简洁用法(@sdcvvc 的第一个解决方案)与轻松打印公式的功能(@sdcvvc 的第二个解决方案)结合起来。

forAll :: (Prop -> Prop) -> Prop
forAll f = ForAll n body
  where body = f (Var n)
        n    = maxBV body + 1

bot :: Name
bot = 0

-- Computes the maximum bound variable in the given expression
maxBV :: Prop -> Name
maxBV (Var _  ) = bot
maxBV (App f a) = maxBV f `max` maxBV a
maxBV (Lam n _) = n

该解决方案将使用如下数据类型:

data Prop 
    = Pred   String [Name]
    | Not    Prop
    | And    Prop  Prop
    | Or     Prop  Prop
    | Impl   Prop  Prop
    | Equiv  Prop  Prop
    | ForAll Name  Prop
    deriving (Eq, Ord)

但允许您将公式编写为:

forAll (\x -> Pred "P" [x] `Impl` Pred "Q" [x])

It seems appropriate to add an answer here to mention the functional pearl Using Circular Programs for Higher-Order Syntax, by Axelsson and Claessen, which was presented at ICFP 2013, and briefly described by Chiusano on his blog.

This solution neatly combines the neat usage of Haskell's syntax (@sdcvvc's first solution) with the ability to easily print formulas (@sdcvvc's second solution).

forAll :: (Prop -> Prop) -> Prop
forAll f = ForAll n body
  where body = f (Var n)
        n    = maxBV body + 1

bot :: Name
bot = 0

-- Computes the maximum bound variable in the given expression
maxBV :: Prop -> Name
maxBV (Var _  ) = bot
maxBV (App f a) = maxBV f `max` maxBV a
maxBV (Lam n _) = n

This solution would use a datatype such as:

data Prop 
    = Pred   String [Name]
    | Not    Prop
    | And    Prop  Prop
    | Or     Prop  Prop
    | Impl   Prop  Prop
    | Equiv  Prop  Prop
    | ForAll Name  Prop
    deriving (Eq, Ord)

But allows you to write formulas as:

forAll (\x -> Pred "P" [x] `Impl` Pred "Q" [x])
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文