104 lines
3.6 KiB
Haskell
Raw Normal View History

2026-01-21 11:24:30 +00:00
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
{-# HLINT ignore "Redundant flip" #-}
2026-01-21 17:11:13 +00:00
{-# LANGUAGE ImportQualifiedPost #-}
2026-01-21 11:24:30 +00:00
module Datalog.NaiveDatabase where
import Data.Map (Map)
import Data.Set (Set)
2026-01-21 17:11:13 +00:00
import Data.Set qualified as Set
import Data.Text (Text)
import qualified Data.Text as T
2026-01-22 17:33:49 +00:00
import Datalog.DatalogParser(parseDatalog, Literal(Literal), Statement(..))
2026-01-21 17:11:13 +00:00
import qualified Data.Map as Map
import Text.Megaparsec (ParseErrorBundle)
import Data.Void
import Control.Exception (Exception)
import Control.Exception.Base
2026-01-21 11:24:30 +00:00
data Value =
ValueInt Int |
ValueSymbol String
data NaiveDatabase = NaiveDatabase {
2026-01-21 18:01:06 +00:00
relations :: Map RelationId Relation,
2026-01-22 10:57:11 +00:00
constants :: Set Constant
2026-01-21 17:11:13 +00:00
}
2026-01-21 18:01:06 +00:00
data Relation = Relation {
arity :: Int,
2026-01-22 10:57:11 +00:00
tuples :: Set [Constant]
2026-01-22 14:25:09 +00:00
} deriving (Show, Eq)
2026-01-21 18:01:06 +00:00
2026-01-22 10:57:11 +00:00
-- newtype RelationId = RelationId Text
-- deriving (Eq, Ord, Show)
2026-01-21 18:01:06 +00:00
2026-01-22 10:57:11 +00:00
-- Our constants will be the terms of the Datalog grammar - ints/variables/symbols
type Constant = Term
type RelationId = Text
-- newtype Constant = Constant Text
-- deriving (Eq, Ord, Show)
2026-01-21 18:01:06 +00:00
2026-01-21 17:11:13 +00:00
emptyDB :: NaiveDatabase
emptyDB = NaiveDatabase {
relations = Map.empty,
2026-01-22 10:57:11 +00:00
constants = Set.empty -- the Herbrand universe
2026-01-21 17:11:13 +00:00
}
withFacts :: [Text] -> NaiveDatabase
withFacts facts =
foldl addFact emptyDB (extractFact <$> facts) where
extractFact:: Text -> Literal
extractFact factText =
case (parseDatalog factText) of
Right (Fact fact) -> fact
Right otherStatement -> throw $ NonFactException factText otherStatement
Left ex -> throw $ CannotParseStatementException factText ex
addFact :: NaiveDatabase -> Literal -> NaiveDatabase
2026-01-22 10:57:11 +00:00
addFact (NaiveDatabase relations constants) (Literal neg relationName terms) =
NaiveDatabase newRelations newConstants where
2026-01-22 14:25:09 +00:00
newArity = length terms
newRelation =
2026-01-22 10:57:11 +00:00
case Map.lookup relationName relations of
2026-01-22 14:25:09 +00:00
Nothing -> Relation (length terms) (Set.singleton terms)
Just relation ->
if (arity relation == newArity)
then Relation (length terms) (Set.singleton terms)
else throw $ BadArityException relationName newArity
newRelations = Map.insert relationName newRelation relations
2026-01-22 10:57:11 +00:00
newConstants = Set.union constants $ Set.fromList terms
2026-01-21 17:11:13 +00:00
2026-01-22 17:33:49 +00:00
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
2026-01-21 17:11:13 +00:00
query :: NaiveDatabase -> Text -> Text
query db qText =
case (parseDatalog qText) of
Right (Query texts literals) -> "#NYI"
Right otherStatement -> throw $ NonQueryException qText otherStatement
Left ex -> throw $ CannotParseStatementException qText ex
data NaiveDatabaseException
= CannotParseStatementException Text (ParseErrorBundle Text Void) |
NonFactException Text Statement |
2026-01-22 17:33:49 +00:00
NonRuleException Text Statement |
2026-01-22 14:25:09 +00:00
NonQueryException Text Statement |
BadArityException Text Int
2026-01-21 17:11:13 +00:00
deriving (Show)
instance Exception NaiveDatabaseException