adding rules to relations

This commit is contained in:
Felix Dilke 2026-01-22 18:00:52 +00:00
parent 2f93c494be
commit 925af95464
2 changed files with 20 additions and 9 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(parseDatalog, Literal(Literal), Statement(..)) import Datalog.DatalogParser(parseDatalog, Literal(Literal), Statement(..), Term, Head (HeadSingle))
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
@ -27,9 +27,20 @@ data NaiveDatabase = NaiveDatabase {
constants :: Set Constant constants :: Set Constant
} }
data BodyEntry = -- entry occurring in a head or body relation - constant or variable
BodyEntryConstant Constant |
BodyEntryVariable Text
deriving (Show, Eq)
data RelationRule = RelationRule {
headVariables :: [BodyEntry],
body :: [(Relation, [BodyEntry])]
} deriving (Show, Eq)
data Relation = Relation { data Relation = Relation {
arity :: Int, arity :: Int,
tuples :: Set [Constant] tuples :: Set [Constant],
rules :: [RelationRule]
} deriving (Show, Eq) } deriving (Show, Eq)
-- newtype RelationId = RelationId Text -- newtype RelationId = RelationId Text
@ -63,10 +74,10 @@ withFacts facts =
newArity = length terms newArity = length terms
newRelation = newRelation =
case Map.lookup relationName relations of case Map.lookup relationName relations of
Nothing -> Relation (length terms) (Set.singleton terms) Nothing -> Relation (length terms) (Set.singleton terms) []
Just relation -> Just relation ->
if (arity relation == newArity) if (arity relation == newArity)
then Relation (length terms) (Set.singleton terms) then Relation (length terms) (Set.singleton terms) []
else throw $ BadArityException relationName newArity else throw $ BadArityException relationName newArity
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
@ -77,11 +88,11 @@ withFactsAndRules facts rules =
extractRule:: Text -> (Literal, [Literal]) extractRule:: Text -> (Literal, [Literal])
extractRule ruleText = extractRule ruleText =
case (parseDatalog ruleText) of case (parseDatalog ruleText) of
Right (Rule lhs rhs) -> (lhs, rhs) Right (Rule (HeadSingle lhs) rhs) -> (lhs, rhs)
Right otherStatement -> throw $ NonRuleException ruleText otherStatement Right otherStatement -> throw $ NonRuleException ruleText otherStatement
Left ex -> throw $ CannotParseStatementException ruleText ex Left ex -> throw $ CannotParseStatementException ruleText ex
addRule :: NaiveDatabase -> Literal -> [Literal] -> NaiveDatabase addRule :: NaiveDatabase -> (Literal, [Literal]) -> NaiveDatabase
addRule (NaiveDatabase relations constants) (Literal neg relationName terms) body = addRule (NaiveDatabase relations constants) ((Literal neg relationName terms), body) =
NaiveDatabase newRelations newConstants where NaiveDatabase newRelations newConstants where
newRelations = relations newRelations = relations
newConstants = constants newConstants = constants

View File

@ -33,7 +33,7 @@ spec = do
relations db `shouldBe` relations db `shouldBe`
Map.fromList [ Map.fromList [
("parent", ("parent",
Relation 2 $ Set.fromList $ [Sym <$> ["bob", "carol"]]) Relation 2 (Set.fromList ([Sym <$> ["bob", "carol"]])) [] )
] ]
it "can ingest facts and rules" $ do it "can ingest facts and rules" $ do
let db = NaiveDatabase.withFactsAndRules let db = NaiveDatabase.withFactsAndRules
@ -46,7 +46,7 @@ spec = do
relations db `shouldBe` relations db `shouldBe`
Map.fromList [ Map.fromList [
("parent", ("parent",
Relation 2 $ Set.fromList $ [Sym <$> ["bob", "carol"]]) Relation 2 (Set.fromList ([Sym <$> ["bob", "carol"]])) [] )
] ]
it "can do basic queries" $ do it "can do basic queries" $ do