packages feed

gargamelle-logic-0.1.0.0: src/Gargamelle/Logic/Signature.hs

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes #-}

module Gargamelle.Logic.Signature
  ( Arity(..)
  , UniversalAlgebraSig(..)
  , LawvereSort(..)
  , LogicAST(..)
  , Entailment(..)
  ) where

import Data.Kind (Type)
import GHC.TypeLits (Nat)

-- | Promoted Arity kind for universal algebra signatures.
data Arity
  = Nullary
  | Unary
  | Binary
  | Nary Nat
  deriving (Eq, Show, Ord)

-- | Textbook Universal Algebra 4-tuple Signature promoted to a Kind via DataKinds.
data UniversalAlgebraSig = UASig
  { functions :: [(String, Arity)]
  , relations :: [(String, Arity)]
  , constants :: [String]
  } deriving (Eq, Show)

-- | Multi-sorted Lawvere theory sort signature mapping input product sorts to output sort.
data LawvereSort sort = LawvereOp [sort] sort
  deriving (Eq, Show)

{- Note [Flat Logic AST Representation]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[tag:note-flat-logic-ast]
In formal verification, SMT piping, and sheaf-theoretic restriction solvers, formulas
frequently contain dozens or hundreds of simultaneous clauses (e.g., global state
invariants, cell complex boundary matchings, and frame conditions).

Representing large n-ary conjunctions as nested binary trees
  (And (And (And A B) C) D)
induces three severe performance penalties:
  1. O(N^2) recursive traversal cost for deep flattening and SMT-LIB2 syntax generation.
  2. High heap allocation from intermediate binary constructor nodes.
  3. GHC call-stack depth exhaustion on deeply nested formulas during pattern matching.

To eliminate this bottleneck, 'LogicAST' incorporates 'FlatConj' and 'FlatDisj' alongside
binary 'And' and 'Or'. 'FlatConj' stores clauses as a flat contiguous list of subformulas,
enabling O(N) linear serialization into SMT-LIB2 s-expressions, trivial constant folding
(pruning 'LitTrue' / 'LitFalse' in a single pass), and cache-friendly iteration.
-}

-- | Observable deep embedding of First-Order Logic indexed by signature kind @k@.
--
-- See Note [Flat Logic AST Representation] [ref:note-flat-logic-ast].
--
-- Avoids native (->) opacity so autonomous agents and SMT pipes can inspect,
-- serialize, and rewrite formulas.
data LogicAST (sig :: k) where
  LitTrue   :: LogicAST sig
  LitFalse  :: LogicAST sig
  AtomPred  :: String -> [String] -> LogicAST sig
  Not       :: LogicAST sig -> LogicAST sig
  And       :: LogicAST sig -> LogicAST sig -> LogicAST sig
  Or        :: LogicAST sig -> LogicAST sig -> LogicAST sig
  Implies   :: LogicAST sig -> LogicAST sig -> LogicAST sig
  Iff       :: LogicAST sig -> LogicAST sig -> LogicAST sig
  Forall    :: String -> LogicAST sig -> LogicAST sig
  Exists    :: String -> LogicAST sig -> LogicAST sig
  -- | Flat contiguous conjunction (prevents O(N^2) nested binary trees)
  FlatConj  :: [LogicAST sig] -> LogicAST sig
  -- | Flat variant disjunction
  FlatDisj  :: [LogicAST sig] -> LogicAST sig

deriving instance Show (LogicAST sig)
deriving instance Eq (LogicAST sig)

-- | Syntactic deductive entailment (⊢) independent of runtime execution.
class Entailment (sen :: k -> Type) where
  entails :: forall (sig :: k). [sen sig] -> sen sig -> Bool