diff --git a/haskell-experiments/CLAUDE.md b/haskell-experiments/CLAUDE.md new file mode 100644 index 0000000..9ea033e --- /dev/null +++ b/haskell-experiments/CLAUDE.md @@ -0,0 +1,48 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Build Commands + +```bash +cabal build # Build the project +cabal test # Run all tests +cabal repl # Start interactive REPL +``` + +To run a single test file or specific test: +```bash +cabal test --test-option=--match="/DatalogParser/" +``` + +## Architecture + +This is an experimental Datalog implementation in Haskell with the following components: + +### Parsing Layer (`src/Datalog/DatalogParser.hs`) +Megaparsec-based parser that converts Datalog text into an AST: +- `Term` - Variables (`Var`), symbols (`Sym`), numbers (`Num`) +- `Literal` - Predicate with arguments, optionally negated +- `Statement` - Fact, Rule (with `Head` and body literals), or Query +- Entry points: `parseDatalog`, `parseDatalogFile` + +### Evaluation Engine (`src/Datalog/NaiveDatabase.hs`) +Naive evaluation database storing relations and rules: +- `NaiveDatabase` - Contains `relations` map and `constants` set (Herbrand universe) +- `Relation` - Name, arity, tuples (facts), and associated rules +- `RelationRule` - Head variables and body constraints +- Key functions: `withFacts`, `withFactsAndRules` for building databases +- Query evaluation is not yet implemented + +### Data Flow +1. Text parsed into `Statement` (Fact/Rule/Query) +2. Facts populate relations with tuples; rules encode derivation logic via `RuleContext` and `BodyConstraint` +3. Variables are indexed during rule processing for efficient constraint matching + +### Other Modules +- `SimpleParser` / `ArithmeticParser` - Experimental arithmetic expression parsers +- `Ologs` - Categorical data structures (dots and arcs representing objects and morphisms) + +## Development Environment + +Nix support via `shell.nix` provides HLS, cabal-install, and Hoogle. Use `direnv allow` for automatic environment loading. diff --git a/haskell-experiments/notes/NaiveDatabase-summary.md b/haskell-experiments/notes/NaiveDatabase-summary.md new file mode 100644 index 0000000..739bb19 --- /dev/null +++ b/haskell-experiments/notes/NaiveDatabase-summary.md @@ -0,0 +1,72 @@ +# NaiveDatabase.hs Summary + +This module implements a naive Datalog database with support for facts, rules, and queries. + +## Data Types + +### Value +A simple algebraic data type representing values in the database. +- `ValueInt Int` - Integer value +- `ValueSymbol String` - Symbolic value + +### NaiveDatabase +The main database structure containing: +- `relations :: Map RelationId Relation` - Map of relation names to relations +- `constants :: Set Constant` - The Herbrand universe (all constants in the database) + +### RuleElement +Represents an entry occurring in a head or body relation. +- `RuleElementConstant Constant` - A constant term +- `RuleElementVariable Text` - A variable name + +### RelationRule +A rule definition containing: +- `headVariables :: [Text]` - List of variable names in the rule head +- `body :: [(Relation, [RuleElement])]` - List of body relations with their elements + +### Relation +A database relation with: +- `_name :: Text` - Relation name +- `_arity :: Int` - Number of columns +- `_tuples :: Set [Constant]` - Set of tuples (facts) +- `_rules :: [RelationRule]` - Associated rules for deriving new tuples + +### ConstraintElement +Represents an entry in a rule body constraint, using indices for variables. +- `ConstraintElementConstant Constant` - A constant term +- `ConstraintElementIndex Int` - Index into the variable list + +### BodyConstraint +A body constraint used during rule processing: +- `_relation :: Relation` - The relation being constrained +- `_elements :: [ConstraintElement]` - List of constraint elements + +### RuleContext +Context maintained while processing rules: +- `__relation :: Relation` - The relation being defined +- `_headVariables :: [RuleElement]` - Variables collected from head and body +- `_bodyConstraints :: [BodyConstraint]` - Constraints from rule body +- `_db :: NaiveDatabase` - Current database state + +### NaiveDatabaseException +Exception types for error handling: +- `CannotParseStatementException` - Failed to parse Datalog text +- `NonFactException` - Expected a fact but got another statement type +- `NonRuleException` - Expected a rule but got another statement type +- `NonQueryException` - Expected a query but got another statement type +- `BadArityException` - Mismatched arity for a relation +- `VariableLookupException` - Variable not found in context +- `UnexpectedConstantException` - Found constant where variable expected + +## Type Aliases + +- `Constant = Term` - Constants are Datalog terms (ints, variables, symbols) +- `RelationId = Text` - Relation identifiers are text strings + +## Key Functions + +- `emptyDB` - Creates an empty database +- `withFacts` - Creates a database from a list of fact texts +- `withFactsAndRules` - Creates a database from facts and rules +- `lookupRelation` - Finds or creates a relation by name +- `query` - Executes a query (currently not yet implemented) diff --git a/haskell-experiments/notes/NaiveDatabase_classes.dot b/haskell-experiments/notes/NaiveDatabase_classes.dot new file mode 100644 index 0000000..5cfd5e2 --- /dev/null +++ b/haskell-experiments/notes/NaiveDatabase_classes.dot @@ -0,0 +1,67 @@ +digraph NaiveDatabase { + rankdir=TB; + node [shape=record, fontname="Helvetica", fontsize=10]; + edge [fontname="Helvetica", fontsize=9]; + + // Main database + NaiveDatabase [label="{NaiveDatabase|relations : Map RelationId Relation\lconstants : Set Constant\l}"]; + + // Core data types + Relation [label="{Relation|_name : Text\l_arity : Int\l_tuples : Set [Constant]\l_rules : [RelationRule]\l}"]; + + RelationRule [label="{RelationRule|headVariables : [Text]\lbody : [(Relation, [RuleElement])]\l}"]; + + RuleElement [label="{RuleElement|RuleElementConstant Constant\l| RuleElementVariable Text\l}"]; + + // Constraint types (used during rule processing) + ConstraintElement [label="{ConstraintElement|ConstraintElementConstant Constant\l| ConstraintElementIndex Int\l}"]; + + BodyConstraint [label="{BodyConstraint|_relation : Relation\l_elements : [ConstraintElement]\l}"]; + + RuleContext [label="{RuleContext|__relation : Relation\l_headVariables : [RuleElement]\l_bodyConstraints : [BodyConstraint]\l_db : NaiveDatabase\l}"]; + + // Type aliases (shown as notes) + TypeAliases [shape=note, label="Type Aliases\l\lConstant = Term\lRelationId = Text\l"]; + + // Value type (standalone) + Value [label="{Value|ValueInt Int\l| ValueSymbol String\l}"]; + + // Exception type + NaiveDatabaseException [label="{NaiveDatabaseException|CannotParseStatementException\l| NonFactException\l| NonRuleException\l| NonQueryException\l| BadArityException\l| VariableLookupException\l| UnexpectedConstantException\l}"]; + + // Relationships + NaiveDatabase -> Relation [label="contains *", style=solid]; + Relation -> RelationRule [label="has *", style=solid]; + RelationRule -> Relation [label="references *", style=dashed]; + RelationRule -> RuleElement [label="contains *", style=solid]; + + BodyConstraint -> Relation [label="references", style=dashed]; + BodyConstraint -> ConstraintElement [label="contains *", style=solid]; + + RuleContext -> Relation [label="references", style=dashed]; + RuleContext -> RuleElement [label="contains *", style=solid]; + RuleContext -> BodyConstraint [label="contains *", style=solid]; + RuleContext -> NaiveDatabase [label="references", style=dashed]; + + // Grouping + subgraph cluster_core { + label="Core Types"; + style=rounded; + color=blue; + NaiveDatabase; Relation; RelationRule; RuleElement; + } + + subgraph cluster_processing { + label="Rule Processing"; + style=rounded; + color=green; + RuleContext; BodyConstraint; ConstraintElement; + } + + subgraph cluster_other { + label="Other"; + style=rounded; + color=gray; + Value; NaiveDatabaseException; TypeAliases; + } +} diff --git a/haskell-experiments/notes/NaiveDatabase_classes.png b/haskell-experiments/notes/NaiveDatabase_classes.png new file mode 100644 index 0000000..0b6c6bc Binary files /dev/null and b/haskell-experiments/notes/NaiveDatabase_classes.png differ