haskell data-structures context-free-grammar first-order-logic

Predicado de lógica en Haskell



data-structures context-free-grammar (2)

Esto se conoce como sintaxis abstracta de orden superior .

Primera solución: usar la lambda de Haskell. Un tipo de datos podría ser similar a:

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)

Puedes escribir una fórmula como:

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

Esto se describe en detalle en el artículo The Monad Reader . Muy recomendable.

Segunda solución:

Use cadenas como

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)

Entonces puedes escribir una fórmula como

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

La ventaja es que puede mostrar la fórmula fácilmente (es difícil mostrar una función Obj -> Prop ). La desventaja es que debe escribir el cambio de nombres en colisión (~ conversión alfa) y sustitución (~ conversión beta). En ambas soluciones, puede usar GADT en lugar de dos tipos de datos:

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

Tercera solución : use los números para representar dónde está vinculada la variable, donde más baja significa más profunda. Por ejemplo, en ForAll (Existe (Igual (Num 0) (Num 1))), la primera variable se vinculará a Exists, y la segunda a ForAll. Esto se conoce como numerales de Bruijn. Ver que no soy un número, soy una variable gratuita .

He estado usando la siguiente estructura de datos para la representación de la lógica proposicional en Haskell:

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

Cualquier comentario sobre esta estructura es bienvenido.

Sin embargo, ahora quiero extender mis algoritmos para manejar FOL - lógica de predicado. ¿Cuál sería una buena forma de representar a FOL en Haskell?

He visto versiones que son, más o menos, una extensión de lo anterior, y versiones que se basan en gramáticas más libres de contexto. ¿Hay literatura sobre esto, que podría recomendarse?


Parece apropiado agregar aquí una respuesta para mencionar la perla funcional Utilizando programas circulares para la sintaxis de orden superior , por Axelsson y Claessen, que se presentó en ICFP 2013, y Chiusano describió brevemente en su blog .

Esta solución combina perfectamente el uso ordenado de la sintaxis de Haskell (la primera solución de @ sdcvvc) con la capacidad de imprimir fórmulas fácilmente (la segunda solución de @ 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

Esta solución usaría un tipo de datos como:

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)

Pero le permite escribir fórmulas como:

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