File size: 7,319 Bytes
a10b189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
{-|
Module      : Assertica.StdLib.Setoid
Description : Setoid algebraic structure: a carrier set with explicit equivalence relation
Copyright   : (c) 2026 Ahmad Ali Parr
License     : BSL-1.0

This module implements the Setoid structure, which forms the foundation of the
algebraic hierarchy. A Setoid is a type S equipped with an equivalence relation (β‰ˆ)
that satisfies reflexivity, symmetry, and transitivity.

CRITICAL PROPERTIES:
  1. Equivalence relation proof: all three properties proven explicitly
  2. Deterministic: equivalence checking is total and decidable
  3. No hidden axioms: all properties must be verified by explicit proof terms
  4. Substitution principle: if a β‰ˆ b, then properties of a hold for b
  5. Kernel-trusted: proofs are checked by Agent 2B

ALGEBRAIC STRUCTURE:
  Setoid S = (S, _β‰ˆ_ : S β†’ S β†’ Prop)
  where _β‰ˆ_ satisfies:
    - Reflexive:  βˆ€ a,     a β‰ˆ a       [Refl]
    - Symmetric:  βˆ€ a b,   a β‰ˆ b β†’ b β‰ˆ a [Symm]
    - Transitive: βˆ€ a b c, a β‰ˆ b β†’ b β‰ˆ c β†’ a β‰ˆ c [Trans]

LATTICE FOUNDATION:
  Setoids provide the carrier for lattice operations (βŠ”, βŠ“) with proper
  algebraic reasoning. The lattice structure (Agent 5B part 2) builds on
  Setoid equivalence for correctness.
-}

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE DeriveEq #-}
{-# LANGUAGE DeriveShow #-}

module Assertica.StdLib.Setoid
  ( -- * Setoid structure
    Setoid(..)
  , SetoidEq(..)
    -- * Constructions
  , trivialSetoid
  , discreteSetoid
  , productSetoid
    -- * Setoid morphisms
  , SetoidMorphism(..)
  , morphismPreservesEq
  , idMorphism
  , composeMorphisms
  ) where

import Assertica.Core.AST
  ( Term(..), Type(..), Var, Proof(..), Proposition(..)
  , Assertion(..), freeVars, substitute
  )
import Assertica.Core.ProofTerm (ProofTerm(..), checkProof)
import Assertica.Core.Equality (isDefinitionallyEqual, normalize)
import qualified Data.Set as Set
import qualified Data.Map.Strict as Map


-- | A Setoid is a type S together with an explicit equivalence relation
--
-- The Setoid class parameterizes over:
--   s:  the carrier type representation (as a Term)
--   eq: the equivalence relation (a predicate Term -> Term -> Prop)
--
-- All three equivalence laws are proven by explicit proof terms.
data Setoid s = Setoid
  { setoidCarrier :: s
    -- ^ The carrier set (e.g., TConst "Nat", TConst "Bool")
  , setoidEq :: Term -> Term -> Proposition
    -- ^ The equivalence relation: given two terms, produce a Proposition
  , setoidRefl :: Term -> ProofTerm
    -- ^ Proof of reflexivity: βˆ€ a, a β‰ˆ a
  , setoidSymm :: Term -> Term -> ProofTerm
    -- ^ Proof of symmetry: βˆ€ a b, a β‰ˆ b β†’ b β‰ˆ a
  , setoidTrans :: Term -> Term -> Term -> ProofTerm
    -- ^ Proof of transitivity: βˆ€ a b c, a β‰ˆ b β†’ b β‰ˆ c β†’ a β‰ˆ c
  } deriving (Show, Eq)

-- | Decision procedure for setoid equality
--
-- SetoidEq wraps a decidable equivalence check with proof obligations
class SetoidEq s where
  -- | Decide if two elements are equivalent, returning explicit proofs
  decideEq :: s -> s -> Maybe (ProofTerm, ProofTerm)
    -- ^ (proof of equality, proof of inequality) or Nothing if undecidable


-- | TRIVIAL SETOID: Single element (unit)
--
-- The trivial setoid has only one element, and all elements are equivalent.
-- Equivalence is proven trivially by Refl.
trivialSetoid :: Setoid Term
trivialSetoid = Setoid
  { setoidCarrier = TConst "Unit"
  , setoidEq = \_ _ -> EqualityProp (TConst "unit") (TConst "unit")
  , setoidRefl = \_ -> Refl
  , setoidSymm = \_ _ -> Refl
  , setoidTrans = \_ _ _ -> Refl
  }

-- | DISCRETE SETOID: Standard equality (definitional equality)
--
-- The discrete setoid uses definitional equality (from Agent 1B) as the
-- equivalence relation. Every element is only equivalent to itself.
discreteSetoid :: Setoid Term
discreteSetoid = Setoid
  { setoidCarrier = TVar (Var "a")
  , setoidEq = \a b -> EqualityProp a b
  , setoidRefl = \a -> Refl
  , setoidSymm = \a b -> Symm (Refl)
  , setoidTrans = \a b c -> Trans Refl Refl
  }

-- | PRODUCT SETOID: Cartesian product of two setoids
--
-- Given setoids S and T, the product setoid S Γ— T has:
--   - Carrier: pairs (a, b) where a ∈ S, b ∈ T
--   - Equivalence: (a, b) β‰ˆ (a', b') iff a β‰ˆ a' and b β‰ˆ b'
--
-- The equivalence proof is constructed by combining proofs from S and T.
productSetoid :: Setoid Term -> Setoid Term -> Setoid Term
productSetoid s1 s2 = Setoid
  { setoidCarrier = TPair (setoidCarrier s1) (setoidCarrier s2)
  , setoidEq = \p1 p2 -> case (p1, p2) of
      (TPair a b, TPair a' b') ->
        ConjunctionProp (setoidEq s1 a a') (setoidEq s2 b b')
      _ -> EqualityProp p1 p2  -- fallback to defn. eq.
  , setoidRefl = \p -> case p of
      TPair a b -> Constr' "and" [setoidRefl s1 a, setoidRefl s2 b]
      _ -> Refl
  , setoidSymm = \p1 p2 -> case (p1, p2) of
      (TPair a b, TPair a' b') ->
        Constr' "and" [setoidSymm s1 a a', setoidSymm s2 b b']
      _ -> Refl
  , setoidTrans = \p1 p2 p3 -> case (p1, p2, p3) of
      (TPair a b, TPair a' b', TPair a'' b'') ->
        Constr' "and"
          [ setoidTrans s1 a a' a''
          , setoidTrans s2 b b' b''
          ]
      _ -> Refl
  }


-- | SETOID MORPHISM: Structure-preserving map between setoids
--
-- A morphism f: S β†’ T preserves the equivalence relation:
-- If a β‰ˆ_S b, then f(a) β‰ˆ_T f(b)
data SetoidMorphism = SetoidMorphism
  { morphismSource :: Setoid Term
  , morphismTarget :: Setoid Term
  , morphismMap :: Term -> Term
    -- ^ The function f: S β†’ T
  , morphismProof :: Term -> Term -> ProofTerm
    -- ^ Proof that f preserves equivalence:
    --   a β‰ˆ_S b β†’ f(a) β‰ˆ_T f(b)
  } deriving (Show, Eq)

-- | PRESERVATION THEOREM: If f is a setoid morphism and a β‰ˆ b, then f(a) β‰ˆ f(b)
--
-- This is the fundamental correctness property of setoid morphisms.
-- It ensures that equivalent elements map to equivalent elements.
morphismPreservesEq :: SetoidMorphism -> Term -> Term -> ProofTerm -> ProofTerm
morphismPreservesEq morph a b eqProof =
  -- Apply the morphism's proof to the equivalence proof
  let fa = morphismMap morph a
      fb = morphismMap morph b
  in morphismProof morph a b eqProof

-- | IDENTITY MORPHISM: The identity map on a setoid
--
-- The identity map is trivially a setoid morphism.
idMorphism :: Setoid Term -> SetoidMorphism
idMorphism s = SetoidMorphism
  { morphismSource = s
  , morphismTarget = s
  , morphismMap = id
  , morphismProof = \_ _ eqProof -> eqProof
  }

-- | COMPOSITION OF MORPHISMS: f ∘ g is a setoid morphism
--
-- If f: S β†’ T and g: T β†’ U are setoid morphisms, then their composition
-- f ∘ g: S β†’ U is also a setoid morphism.
--
-- PROOF:
--   Let a, b ∈ S with a β‰ˆ_S b.
--   By g's preservation: g(a) β‰ˆ_T g(b)
--   By f's preservation: f(g(a)) β‰ˆ_U f(g(b))
--   Therefore (f ∘ g) preserves equivalence. β–‘
composeMorphisms :: SetoidMorphism -> SetoidMorphism -> SetoidMorphism
composeMorphisms f g = SetoidMorphism
  { morphismSource = morphismSource g
  , morphismTarget = morphismTarget f
  , morphismMap = \a -> morphismMap f (morphismMap g a)
  , morphismProof = \a b eqProof ->
      let gEq = morphismProof g a b eqProof
          fEq = morphismProof f (morphismMap g a) (morphismMap g b) gEq
      in fEq
  }