initial handling of rules

This commit is contained in:
Felix Dilke 2026-01-22 17:33:49 +00:00
parent 5caf061fce
commit 2f93c494be
2 changed files with 30 additions and 1 deletions

View File

@ -11,7 +11,7 @@ import Data.Set (Set)
import Data.Set qualified as Set import Data.Set qualified as Set
import Data.Text (Text) import Data.Text (Text)
import qualified Data.Text as T import qualified Data.Text as T
import Datalog.DatalogParser import Datalog.DatalogParser(parseDatalog, Literal(Literal), Statement(..))
import qualified Data.Map as Map import qualified Data.Map as Map
import Text.Megaparsec (ParseErrorBundle) import Text.Megaparsec (ParseErrorBundle)
import Data.Void import Data.Void
@ -71,6 +71,21 @@ withFacts facts =
newRelations = Map.insert relationName newRelation relations newRelations = Map.insert relationName newRelation relations
newConstants = Set.union constants $ Set.fromList terms newConstants = Set.union constants $ Set.fromList terms
withFactsAndRules :: [Text] -> [Text] -> NaiveDatabase
withFactsAndRules facts rules =
foldl addRule (withFacts facts) (extractRule <$> rules) where
extractRule:: Text -> (Literal, [Literal])
extractRule ruleText =
case (parseDatalog ruleText) of
Right (Rule lhs rhs) -> (lhs, rhs)
Right otherStatement -> throw $ NonRuleException ruleText otherStatement
Left ex -> throw $ CannotParseStatementException ruleText ex
addRule :: NaiveDatabase -> Literal -> [Literal] -> NaiveDatabase
addRule (NaiveDatabase relations constants) (Literal neg relationName terms) body =
NaiveDatabase newRelations newConstants where
newRelations = relations
newConstants = constants
query :: NaiveDatabase -> Text -> Text query :: NaiveDatabase -> Text -> Text
query db qText = query db qText =
case (parseDatalog qText) of case (parseDatalog qText) of
@ -81,6 +96,7 @@ query db qText =
data NaiveDatabaseException data NaiveDatabaseException
= CannotParseStatementException Text (ParseErrorBundle Text Void) | = CannotParseStatementException Text (ParseErrorBundle Text Void) |
NonFactException Text Statement | NonFactException Text Statement |
NonRuleException Text Statement |
NonQueryException Text Statement | NonQueryException Text Statement |
BadArityException Text Int BadArityException Text Int
deriving (Show) deriving (Show)

View File

@ -35,6 +35,19 @@ spec = do
("parent", ("parent",
Relation 2 $ Set.fromList $ [Sym <$> ["bob", "carol"]]) Relation 2 $ Set.fromList $ [Sym <$> ["bob", "carol"]])
] ]
it "can ingest facts and rules" $ do
let db = NaiveDatabase.withFactsAndRules
[ "parent(\"alice\", \"bob\")."
, "parent(\"bob\", \"carol\")." ]
[ "ancestor(X,Y) :- parent(X,Y)."
, "ancestor(X,Y) :- parent(X,Z), ancestor(Z,Y)." ]
constants db `shouldBe`
(Set.fromList $ Sym <$> ["alice", "bob", "carol"])
relations db `shouldBe`
Map.fromList [
("parent",
Relation 2 $ Set.fromList $ [Sym <$> ["bob", "carol"]])
]
it "can do basic queries" $ do it "can do basic queries" $ do
let db = NaiveDatabase.withFacts let db = NaiveDatabase.withFacts