mcard-js 2.1.1 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/ptr/lambda/AlphaConversion.d.ts +42 -0
- package/dist/ptr/lambda/AlphaConversion.d.ts.map +1 -0
- package/dist/ptr/lambda/AlphaConversion.js +244 -0
- package/dist/ptr/lambda/AlphaConversion.js.map +1 -0
- package/dist/ptr/lambda/BetaReduction.d.ts +73 -0
- package/dist/ptr/lambda/BetaReduction.d.ts.map +1 -0
- package/dist/ptr/lambda/BetaReduction.js +322 -0
- package/dist/ptr/lambda/BetaReduction.js.map +1 -0
- package/dist/ptr/lambda/EtaConversion.d.ts +65 -0
- package/dist/ptr/lambda/EtaConversion.d.ts.map +1 -0
- package/dist/ptr/lambda/EtaConversion.js +228 -0
- package/dist/ptr/lambda/EtaConversion.js.map +1 -0
- package/dist/ptr/lambda/FreeVariables.d.ts +44 -0
- package/dist/ptr/lambda/FreeVariables.d.ts.map +1 -0
- package/dist/ptr/lambda/FreeVariables.js +207 -0
- package/dist/ptr/lambda/FreeVariables.js.map +1 -0
- package/dist/ptr/lambda/LambdaRuntime.d.ts +80 -0
- package/dist/ptr/lambda/LambdaRuntime.d.ts.map +1 -0
- package/dist/ptr/lambda/LambdaRuntime.js +417 -0
- package/dist/ptr/lambda/LambdaRuntime.js.map +1 -0
- package/dist/ptr/lambda/LambdaTerm.d.ts +95 -0
- package/dist/ptr/lambda/LambdaTerm.d.ts.map +1 -0
- package/dist/ptr/lambda/LambdaTerm.js +159 -0
- package/dist/ptr/lambda/LambdaTerm.js.map +1 -0
- package/dist/ptr/lambda/index.d.ts +24 -0
- package/dist/ptr/lambda/index.d.ts.map +1 -0
- package/dist/ptr/lambda/index.js +34 -0
- package/dist/ptr/lambda/index.js.map +1 -0
- package/dist/ptr/node/CLMRunner.d.ts +30 -0
- package/dist/ptr/node/CLMRunner.d.ts.map +1 -1
- package/dist/ptr/node/CLMRunner.js +167 -0
- package/dist/ptr/node/CLMRunner.js.map +1 -1
- package/dist/ptr/node/Runtimes.d.ts +8 -1
- package/dist/ptr/node/Runtimes.d.ts.map +1 -1
- package/dist/ptr/node/Runtimes.js +8 -1
- package/dist/ptr/node/Runtimes.js.map +1 -1
- package/dist/storage/schema.d.ts.map +1 -1
- package/dist/storage/schema.js +5 -1
- package/dist/storage/schema.js.map +1 -1
- package/package.json +6 -2
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Beta Reduction (β-reduction)
|
|
3
|
+
*
|
|
4
|
+
* The computational heart of Lambda Calculus - function application.
|
|
5
|
+
*
|
|
6
|
+
* Rule: (λx.M) N →β M[x:=N]
|
|
7
|
+
*
|
|
8
|
+
* A term of the form (λx.M) N is called a "beta-redex" (reducible expression).
|
|
9
|
+
* Beta reduction substitutes the argument N for all free occurrences of x in M.
|
|
10
|
+
*
|
|
11
|
+
* IMPORTANT: Must handle capture avoidance - if N contains free variables
|
|
12
|
+
* that would become bound in M, we must α-rename first.
|
|
13
|
+
*
|
|
14
|
+
* @module mcard-js/ptr/lambda/BetaReduction
|
|
15
|
+
*/
|
|
16
|
+
import { loadTerm, storeTerm, mkAbs, mkApp, isAbs, isApp } from './LambdaTerm';
|
|
17
|
+
import { freeVariables, generateFresh } from './FreeVariables';
|
|
18
|
+
import { alphaRename } from './AlphaConversion';
|
|
19
|
+
import { IO } from '../../monads/IO';
|
|
20
|
+
import { Either } from '../../monads/Either';
|
|
21
|
+
import { Maybe } from '../../monads/Maybe';
|
|
22
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
23
|
+
// Beta Redex Detection
|
|
24
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
25
|
+
/**
|
|
26
|
+
* Check if a term is a beta-redex: (λx.M) N
|
|
27
|
+
*/
|
|
28
|
+
export function isRedex(collection, termHash) {
|
|
29
|
+
return IO.of(async () => {
|
|
30
|
+
const term = await loadTerm(collection, termHash);
|
|
31
|
+
if (!term || !isApp(term))
|
|
32
|
+
return false;
|
|
33
|
+
const func = await loadTerm(collection, term.func);
|
|
34
|
+
return func !== null && isAbs(func);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Find the leftmost-outermost redex (normal order reduction)
|
|
39
|
+
* Returns Maybe<hash of redex>
|
|
40
|
+
*/
|
|
41
|
+
export function findLeftmostRedex(collection, termHash) {
|
|
42
|
+
return IO.of(async () => {
|
|
43
|
+
return findRedexNormalOrder(collection, termHash);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
async function findRedexNormalOrder(collection, termHash) {
|
|
47
|
+
const term = await loadTerm(collection, termHash);
|
|
48
|
+
if (!term)
|
|
49
|
+
return Maybe.nothing();
|
|
50
|
+
switch (term.tag) {
|
|
51
|
+
case 'Var':
|
|
52
|
+
// Variables are not redexes
|
|
53
|
+
return Maybe.nothing();
|
|
54
|
+
case 'Abs':
|
|
55
|
+
// Look inside the body
|
|
56
|
+
return findRedexNormalOrder(collection, term.body);
|
|
57
|
+
case 'App': {
|
|
58
|
+
// Check if this application is a redex
|
|
59
|
+
const func = await loadTerm(collection, term.func);
|
|
60
|
+
if (func && isAbs(func)) {
|
|
61
|
+
// This is a redex!
|
|
62
|
+
return Maybe.just(termHash);
|
|
63
|
+
}
|
|
64
|
+
// Not a redex - search in func first (leftmost), then arg
|
|
65
|
+
const funcRedex = await findRedexNormalOrder(collection, term.func);
|
|
66
|
+
if (funcRedex.isJust)
|
|
67
|
+
return funcRedex;
|
|
68
|
+
return findRedexNormalOrder(collection, term.arg);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Find the leftmost-innermost redex (applicative order reduction)
|
|
74
|
+
*/
|
|
75
|
+
export function findInnermostRedex(collection, termHash) {
|
|
76
|
+
return IO.of(async () => {
|
|
77
|
+
return findRedexApplicativeOrder(collection, termHash);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
async function findRedexApplicativeOrder(collection, termHash) {
|
|
81
|
+
const term = await loadTerm(collection, termHash);
|
|
82
|
+
if (!term)
|
|
83
|
+
return Maybe.nothing();
|
|
84
|
+
switch (term.tag) {
|
|
85
|
+
case 'Var':
|
|
86
|
+
return Maybe.nothing();
|
|
87
|
+
case 'Abs':
|
|
88
|
+
return findRedexApplicativeOrder(collection, term.body);
|
|
89
|
+
case 'App': {
|
|
90
|
+
// Search in subterms first (innermost)
|
|
91
|
+
const funcRedex = await findRedexApplicativeOrder(collection, term.func);
|
|
92
|
+
if (funcRedex.isJust)
|
|
93
|
+
return funcRedex;
|
|
94
|
+
const argRedex = await findRedexApplicativeOrder(collection, term.arg);
|
|
95
|
+
if (argRedex.isJust)
|
|
96
|
+
return argRedex;
|
|
97
|
+
// Then check if this is a redex
|
|
98
|
+
const func = await loadTerm(collection, term.func);
|
|
99
|
+
if (func && isAbs(func)) {
|
|
100
|
+
return Maybe.just(termHash);
|
|
101
|
+
}
|
|
102
|
+
return Maybe.nothing();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
107
|
+
// Beta Reduction
|
|
108
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
109
|
+
/**
|
|
110
|
+
* Perform a single beta reduction step on a redex
|
|
111
|
+
*
|
|
112
|
+
* (λx.M) N →β M[x:=N]
|
|
113
|
+
*
|
|
114
|
+
* @param collection - Card collection
|
|
115
|
+
* @param redexHash - Hash of the application term (λx.M) N
|
|
116
|
+
* @returns Either<error, resultHash>
|
|
117
|
+
*/
|
|
118
|
+
export function betaReduce(collection, redexHash) {
|
|
119
|
+
return IO.of(async () => {
|
|
120
|
+
const app = await loadTerm(collection, redexHash);
|
|
121
|
+
if (!app) {
|
|
122
|
+
return Either.left(`Term not found: ${redexHash}`);
|
|
123
|
+
}
|
|
124
|
+
if (!isApp(app)) {
|
|
125
|
+
return Either.left(`Beta reduction requires application term, got ${app.tag}`);
|
|
126
|
+
}
|
|
127
|
+
const func = await loadTerm(collection, app.func);
|
|
128
|
+
if (!func) {
|
|
129
|
+
return Either.left(`Function not found: ${app.func}`);
|
|
130
|
+
}
|
|
131
|
+
if (!isAbs(func)) {
|
|
132
|
+
return Either.left(`Not a beta-redex: function is ${func.tag}, not abstraction`);
|
|
133
|
+
}
|
|
134
|
+
// Perform substitution: M[x:=N]
|
|
135
|
+
const resultHash = await substituteWithCapture(collection, func.body, // M
|
|
136
|
+
func.param, // x
|
|
137
|
+
app.arg // N (as hash)
|
|
138
|
+
);
|
|
139
|
+
return Either.right(resultHash);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Substitute a variable with a term (by hash), handling capture avoidance
|
|
144
|
+
*
|
|
145
|
+
* M[x:=N] - replaces all free occurrences of x in M with N
|
|
146
|
+
*/
|
|
147
|
+
async function substituteWithCapture(collection, termHash, variable, replacementHash) {
|
|
148
|
+
const term = await loadTerm(collection, termHash);
|
|
149
|
+
if (!term) {
|
|
150
|
+
throw new Error(`Term not found: ${termHash}`);
|
|
151
|
+
}
|
|
152
|
+
switch (term.tag) {
|
|
153
|
+
case 'Var':
|
|
154
|
+
// If this is the variable we're substituting, return the replacement
|
|
155
|
+
if (term.name === variable) {
|
|
156
|
+
return replacementHash;
|
|
157
|
+
}
|
|
158
|
+
// Otherwise unchanged
|
|
159
|
+
return termHash;
|
|
160
|
+
case 'Abs': {
|
|
161
|
+
// If bound variable shadows, stop substitution
|
|
162
|
+
if (term.param === variable) {
|
|
163
|
+
return termHash;
|
|
164
|
+
}
|
|
165
|
+
// Check for variable capture:
|
|
166
|
+
// If the bound variable (term.param) is free in the replacement,
|
|
167
|
+
// we must α-rename to avoid capture
|
|
168
|
+
const replacementFV = await freeVariables(collection, replacementHash).run();
|
|
169
|
+
if (replacementFV.isJust && replacementFV.value.has(term.param)) {
|
|
170
|
+
// Capture would occur! Need to α-rename first
|
|
171
|
+
const allVars = new Set(replacementFV.value);
|
|
172
|
+
// Also avoid variables in the body
|
|
173
|
+
const bodyFV = await freeVariables(collection, term.body).run();
|
|
174
|
+
if (bodyFV.isJust) {
|
|
175
|
+
for (const v of bodyFV.value)
|
|
176
|
+
allVars.add(v);
|
|
177
|
+
}
|
|
178
|
+
allVars.add(variable);
|
|
179
|
+
// Generate fresh name
|
|
180
|
+
const freshName = generateFresh(term.param, allVars);
|
|
181
|
+
// α-rename the abstraction
|
|
182
|
+
const renameResult = await alphaRename(collection, termHash, freshName).run();
|
|
183
|
+
if (renameResult.isLeft) {
|
|
184
|
+
throw new Error(`Alpha rename failed: ${renameResult.left}`);
|
|
185
|
+
}
|
|
186
|
+
// Now substitute in the renamed term
|
|
187
|
+
return substituteWithCapture(collection, renameResult.right, variable, replacementHash);
|
|
188
|
+
}
|
|
189
|
+
// No capture - recurse into body
|
|
190
|
+
const newBody = await substituteWithCapture(collection, term.body, variable, replacementHash);
|
|
191
|
+
if (newBody === term.body) {
|
|
192
|
+
return termHash;
|
|
193
|
+
}
|
|
194
|
+
const newAbs = mkAbs(term.param, newBody);
|
|
195
|
+
return storeTerm(collection, newAbs);
|
|
196
|
+
}
|
|
197
|
+
case 'App': {
|
|
198
|
+
const newFunc = await substituteWithCapture(collection, term.func, variable, replacementHash);
|
|
199
|
+
const newArg = await substituteWithCapture(collection, term.arg, variable, replacementHash);
|
|
200
|
+
if (newFunc === term.func && newArg === term.arg) {
|
|
201
|
+
return termHash;
|
|
202
|
+
}
|
|
203
|
+
const newApp = mkApp(newFunc, newArg);
|
|
204
|
+
return storeTerm(collection, newApp);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Perform one reduction step using the specified strategy
|
|
210
|
+
*/
|
|
211
|
+
export function reduceStep(collection, termHash, strategy = 'normal') {
|
|
212
|
+
return IO.of(async () => {
|
|
213
|
+
// Find redex using strategy
|
|
214
|
+
let redexMaybe;
|
|
215
|
+
switch (strategy) {
|
|
216
|
+
case 'normal':
|
|
217
|
+
case 'lazy':
|
|
218
|
+
redexMaybe = await findRedexNormalOrder(collection, termHash);
|
|
219
|
+
break;
|
|
220
|
+
case 'applicative':
|
|
221
|
+
redexMaybe = await findRedexApplicativeOrder(collection, termHash);
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
if (redexMaybe.isNothing) {
|
|
225
|
+
// No redex found - already in normal form
|
|
226
|
+
return Maybe.nothing();
|
|
227
|
+
}
|
|
228
|
+
const redexHash = redexMaybe.value;
|
|
229
|
+
// If the redex is the whole term, just reduce it
|
|
230
|
+
if (redexHash === termHash) {
|
|
231
|
+
const result = await betaReduce(collection, redexHash).run();
|
|
232
|
+
if (result.isLeft) {
|
|
233
|
+
throw new Error(result.left);
|
|
234
|
+
}
|
|
235
|
+
return Maybe.just(result.right);
|
|
236
|
+
}
|
|
237
|
+
// Otherwise, need to reduce the subterm and reconstruct
|
|
238
|
+
const reduced = await betaReduce(collection, redexHash).run();
|
|
239
|
+
if (reduced.isLeft) {
|
|
240
|
+
throw new Error(reduced.left);
|
|
241
|
+
}
|
|
242
|
+
const rebuilt = await rebuildWithReduced(collection, termHash, redexHash, reduced.right);
|
|
243
|
+
return Maybe.just(rebuilt);
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Rebuild a term after reducing a subterm
|
|
248
|
+
*/
|
|
249
|
+
async function rebuildWithReduced(collection, termHash, redexHash, reducedHash) {
|
|
250
|
+
if (termHash === redexHash) {
|
|
251
|
+
return reducedHash;
|
|
252
|
+
}
|
|
253
|
+
const term = await loadTerm(collection, termHash);
|
|
254
|
+
if (!term)
|
|
255
|
+
throw new Error(`Term not found: ${termHash}`);
|
|
256
|
+
switch (term.tag) {
|
|
257
|
+
case 'Var':
|
|
258
|
+
return termHash;
|
|
259
|
+
case 'Abs': {
|
|
260
|
+
const newBody = await rebuildWithReduced(collection, term.body, redexHash, reducedHash);
|
|
261
|
+
if (newBody === term.body)
|
|
262
|
+
return termHash;
|
|
263
|
+
const newAbs = mkAbs(term.param, newBody);
|
|
264
|
+
return storeTerm(collection, newAbs);
|
|
265
|
+
}
|
|
266
|
+
case 'App': {
|
|
267
|
+
const newFunc = await rebuildWithReduced(collection, term.func, redexHash, reducedHash);
|
|
268
|
+
const newArg = await rebuildWithReduced(collection, term.arg, redexHash, reducedHash);
|
|
269
|
+
if (newFunc === term.func && newArg === term.arg)
|
|
270
|
+
return termHash;
|
|
271
|
+
const newApp = mkApp(newFunc, newArg);
|
|
272
|
+
return storeTerm(collection, newApp);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Normalize a term to its normal form (no more redexes)
|
|
278
|
+
*
|
|
279
|
+
* @param collection - Card collection
|
|
280
|
+
* @param termHash - Starting term
|
|
281
|
+
* @param strategy - Reduction strategy
|
|
282
|
+
* @param maxSteps - Maximum reduction steps (prevent infinite loops)
|
|
283
|
+
* @returns Either<error, NormalizationResult>
|
|
284
|
+
*/
|
|
285
|
+
export function normalize(collection, termHash, strategy = 'normal', maxSteps = 1000) {
|
|
286
|
+
return IO.of(async () => {
|
|
287
|
+
let current = termHash;
|
|
288
|
+
let steps = 0;
|
|
289
|
+
const path = [termHash];
|
|
290
|
+
while (steps < maxSteps) {
|
|
291
|
+
const stepResult = await reduceStep(collection, current, strategy).run();
|
|
292
|
+
if (stepResult.isNothing) {
|
|
293
|
+
// No more reductions - reached normal form
|
|
294
|
+
return Either.right({
|
|
295
|
+
normalForm: current,
|
|
296
|
+
steps,
|
|
297
|
+
reductionPath: path
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
current = stepResult.value;
|
|
301
|
+
path.push(current);
|
|
302
|
+
steps++;
|
|
303
|
+
}
|
|
304
|
+
return Either.left(`Normalization did not terminate within ${maxSteps} steps (possible infinite loop)`);
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Check if a term is in normal form (has no redexes)
|
|
309
|
+
*/
|
|
310
|
+
export function isNormalForm(collection, termHash) {
|
|
311
|
+
return findLeftmostRedex(collection, termHash).map(m => m.isNothing);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Check if a term has a normal form (is normalizing)
|
|
315
|
+
*
|
|
316
|
+
* Note: This is undecidable in general, so we use a bounded check
|
|
317
|
+
*/
|
|
318
|
+
export function hasNormalForm(collection, termHash, maxSteps = 1000) {
|
|
319
|
+
return normalize(collection, termHash, 'normal', maxSteps)
|
|
320
|
+
.map(result => result.isRight);
|
|
321
|
+
}
|
|
322
|
+
//# sourceMappingURL=BetaReduction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BetaReduction.js","sourceRoot":"","sources":["../../../src/ptr/lambda/BetaReduction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Eta Conversion (η-conversion)
|
|
3
|
+
*
|
|
4
|
+
* Captures extensional equality of functions.
|
|
5
|
+
*
|
|
6
|
+
* η-reduction: λx.(f x) →η f (if x ∉ FV(f))
|
|
7
|
+
* η-expansion: f →η λx.(f x) (where x is fresh)
|
|
8
|
+
*
|
|
9
|
+
* Two functions are η-equivalent if they produce the same output for all inputs.
|
|
10
|
+
* This is the principle of extensionality: functions are determined by their behavior.
|
|
11
|
+
*
|
|
12
|
+
* @module mcard-js/ptr/lambda/EtaConversion
|
|
13
|
+
*/
|
|
14
|
+
import { CardCollection } from '../../model/CardCollection';
|
|
15
|
+
import { IO } from '../../monads/IO';
|
|
16
|
+
import { Either } from '../../monads/Either';
|
|
17
|
+
import { Maybe } from '../../monads/Maybe';
|
|
18
|
+
/**
|
|
19
|
+
* Check if a term is an η-redex: λx.(f x) where x ∉ FV(f)
|
|
20
|
+
*/
|
|
21
|
+
export declare function isEtaRedex(collection: CardCollection, termHash: string): IO<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* Eta reduction: λx.(f x) →η f
|
|
24
|
+
*
|
|
25
|
+
* Only valid if x does not occur free in f.
|
|
26
|
+
*
|
|
27
|
+
* @param collection - Card collection
|
|
28
|
+
* @param termHash - Hash of the abstraction λx.(f x)
|
|
29
|
+
* @returns Maybe<resultHash> - Nothing if not an η-redex
|
|
30
|
+
*/
|
|
31
|
+
export declare function etaReduce(collection: CardCollection, termHash: string): IO<Maybe<string>>;
|
|
32
|
+
/**
|
|
33
|
+
* Try eta reduction, returning Either for error handling
|
|
34
|
+
*/
|
|
35
|
+
export declare function etaReduceE(collection: CardCollection, termHash: string): IO<Either<string, string>>;
|
|
36
|
+
/**
|
|
37
|
+
* Eta expansion: f →η λx.(f x)
|
|
38
|
+
*
|
|
39
|
+
* Wraps a function in a lambda that immediately applies it.
|
|
40
|
+
* The new variable must be fresh (not occurring in f).
|
|
41
|
+
*
|
|
42
|
+
* @param collection - Card collection
|
|
43
|
+
* @param termHash - Hash of the term to expand
|
|
44
|
+
* @param baseName - Base name for the fresh variable (default: 'x')
|
|
45
|
+
* @returns Hash of the expanded term λx.(f x)
|
|
46
|
+
*/
|
|
47
|
+
export declare function etaExpand(collection: CardCollection, termHash: string, baseName?: string): IO<string>;
|
|
48
|
+
/**
|
|
49
|
+
* Check if two terms are η-equivalent
|
|
50
|
+
*
|
|
51
|
+
* Two terms f and g are η-equivalent if:
|
|
52
|
+
* - They are the same, or
|
|
53
|
+
* - One η-reduces to the other, or
|
|
54
|
+
* - They both η-expand to equivalent terms
|
|
55
|
+
*/
|
|
56
|
+
export declare function etaEquivalent(collection: CardCollection, hash1: string, hash2: string): IO<boolean>;
|
|
57
|
+
/**
|
|
58
|
+
* Eta-normalize a term by reducing all η-redexes
|
|
59
|
+
*/
|
|
60
|
+
export declare function etaNormalize(collection: CardCollection, termHash: string): IO<string>;
|
|
61
|
+
/**
|
|
62
|
+
* Find all η-redexes in a term
|
|
63
|
+
*/
|
|
64
|
+
export declare function findEtaRedexes(collection: CardCollection, termHash: string): IO<string[]>;
|
|
65
|
+
//# sourceMappingURL=EtaConversion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EtaConversion.d.ts","sourceRoot":"","sources":["../../../src/ptr/lambda/EtaConversion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAa5D,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAM3C;;GAEG;AACH,wBAAgB,UAAU,CACtB,UAAU,EAAE,cAAc,EAC1B,QAAQ,EAAE,MAAM,GACjB,EAAE,CAAC,OAAO,CAAC,CAkBb;AAMD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CACrB,UAAU,EAAE,cAAc,EAC1B,QAAQ,EAAE,MAAM,GACjB,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAiCnB;AAED;;GAEG;AACH,wBAAgB,UAAU,CACtB,UAAU,EAAE,cAAc,EAC1B,QAAQ,EAAE,MAAM,GACjB,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAO5B;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CACrB,UAAU,EAAE,cAAc,EAC1B,QAAQ,EAAE,MAAM,EAChB,QAAQ,GAAE,MAAY,GACvB,EAAE,CAAC,MAAM,CAAC,CAmBZ;AAMD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CACzB,UAAU,EAAE,cAAc,EAC1B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACd,EAAE,CAAC,OAAO,CAAC,CAWb;AAgDD;;GAEG;AACH,wBAAgB,YAAY,CACxB,UAAU,EAAE,cAAc,EAC1B,QAAQ,EAAE,MAAM,GACjB,EAAE,CAAC,MAAM,CAAC,CAEZ;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC1B,UAAU,EAAE,cAAc,EAC1B,QAAQ,EAAE,MAAM,GACjB,EAAE,CAAC,MAAM,EAAE,CAAC,CAMd"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Eta Conversion (η-conversion)
|
|
3
|
+
*
|
|
4
|
+
* Captures extensional equality of functions.
|
|
5
|
+
*
|
|
6
|
+
* η-reduction: λx.(f x) →η f (if x ∉ FV(f))
|
|
7
|
+
* η-expansion: f →η λx.(f x) (where x is fresh)
|
|
8
|
+
*
|
|
9
|
+
* Two functions are η-equivalent if they produce the same output for all inputs.
|
|
10
|
+
* This is the principle of extensionality: functions are determined by their behavior.
|
|
11
|
+
*
|
|
12
|
+
* @module mcard-js/ptr/lambda/EtaConversion
|
|
13
|
+
*/
|
|
14
|
+
import { loadTerm, storeTerm, mkVar, mkAbs, mkApp, isVar, isAbs, isApp } from './LambdaTerm';
|
|
15
|
+
import { freeVariables, generateFreshFor } from './FreeVariables';
|
|
16
|
+
import { IO } from '../../monads/IO';
|
|
17
|
+
import { Either } from '../../monads/Either';
|
|
18
|
+
import { Maybe } from '../../monads/Maybe';
|
|
19
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
20
|
+
// Eta Redex Detection
|
|
21
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
22
|
+
/**
|
|
23
|
+
* Check if a term is an η-redex: λx.(f x) where x ∉ FV(f)
|
|
24
|
+
*/
|
|
25
|
+
export function isEtaRedex(collection, termHash) {
|
|
26
|
+
return IO.of(async () => {
|
|
27
|
+
const term = await loadTerm(collection, termHash);
|
|
28
|
+
if (!term || !isAbs(term))
|
|
29
|
+
return false;
|
|
30
|
+
const body = await loadTerm(collection, term.body);
|
|
31
|
+
if (!body || !isApp(body))
|
|
32
|
+
return false;
|
|
33
|
+
// Check if argument is the bound variable
|
|
34
|
+
const arg = await loadTerm(collection, body.arg);
|
|
35
|
+
if (!arg || !isVar(arg) || arg.name !== term.param)
|
|
36
|
+
return false;
|
|
37
|
+
// Check if x is not free in f
|
|
38
|
+
const funcFV = await freeVariables(collection, body.func).run();
|
|
39
|
+
if (funcFV.isNothing)
|
|
40
|
+
return false;
|
|
41
|
+
return !funcFV.value.has(term.param);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
45
|
+
// Eta Reduction
|
|
46
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
47
|
+
/**
|
|
48
|
+
* Eta reduction: λx.(f x) →η f
|
|
49
|
+
*
|
|
50
|
+
* Only valid if x does not occur free in f.
|
|
51
|
+
*
|
|
52
|
+
* @param collection - Card collection
|
|
53
|
+
* @param termHash - Hash of the abstraction λx.(f x)
|
|
54
|
+
* @returns Maybe<resultHash> - Nothing if not an η-redex
|
|
55
|
+
*/
|
|
56
|
+
export function etaReduce(collection, termHash) {
|
|
57
|
+
return IO.of(async () => {
|
|
58
|
+
const term = await loadTerm(collection, termHash);
|
|
59
|
+
if (!term)
|
|
60
|
+
return Maybe.nothing();
|
|
61
|
+
// Must be λx.E
|
|
62
|
+
if (!isAbs(term))
|
|
63
|
+
return Maybe.nothing();
|
|
64
|
+
const body = await loadTerm(collection, term.body);
|
|
65
|
+
if (!body)
|
|
66
|
+
return Maybe.nothing();
|
|
67
|
+
// Body must be application (f x)
|
|
68
|
+
if (!isApp(body))
|
|
69
|
+
return Maybe.nothing();
|
|
70
|
+
// Argument must be the bound variable
|
|
71
|
+
const arg = await loadTerm(collection, body.arg);
|
|
72
|
+
if (!arg)
|
|
73
|
+
return Maybe.nothing();
|
|
74
|
+
if (!isVar(arg) || arg.name !== term.param) {
|
|
75
|
+
return Maybe.nothing();
|
|
76
|
+
}
|
|
77
|
+
// x must not be free in f
|
|
78
|
+
const funcFV = await freeVariables(collection, body.func).run();
|
|
79
|
+
if (funcFV.isNothing)
|
|
80
|
+
return Maybe.nothing();
|
|
81
|
+
if (funcFV.value.has(term.param)) {
|
|
82
|
+
return Maybe.nothing();
|
|
83
|
+
}
|
|
84
|
+
// η-reduce: return f's hash
|
|
85
|
+
return Maybe.just(body.func);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Try eta reduction, returning Either for error handling
|
|
90
|
+
*/
|
|
91
|
+
export function etaReduceE(collection, termHash) {
|
|
92
|
+
return etaReduce(collection, termHash).map(maybe => {
|
|
93
|
+
if (maybe.isNothing) {
|
|
94
|
+
return Either.left('Not an η-redex');
|
|
95
|
+
}
|
|
96
|
+
return Either.right(maybe.value);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
100
|
+
// Eta Expansion
|
|
101
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
102
|
+
/**
|
|
103
|
+
* Eta expansion: f →η λx.(f x)
|
|
104
|
+
*
|
|
105
|
+
* Wraps a function in a lambda that immediately applies it.
|
|
106
|
+
* The new variable must be fresh (not occurring in f).
|
|
107
|
+
*
|
|
108
|
+
* @param collection - Card collection
|
|
109
|
+
* @param termHash - Hash of the term to expand
|
|
110
|
+
* @param baseName - Base name for the fresh variable (default: 'x')
|
|
111
|
+
* @returns Hash of the expanded term λx.(f x)
|
|
112
|
+
*/
|
|
113
|
+
export function etaExpand(collection, termHash, baseName = 'x') {
|
|
114
|
+
return IO.of(async () => {
|
|
115
|
+
// Generate fresh variable name
|
|
116
|
+
const freshVar = await generateFreshFor(collection, baseName, termHash);
|
|
117
|
+
// Create variable term
|
|
118
|
+
const varTerm = mkVar(freshVar);
|
|
119
|
+
const varHash = await storeTerm(collection, varTerm);
|
|
120
|
+
// Create application (f x)
|
|
121
|
+
const appTerm = mkApp(termHash, varHash);
|
|
122
|
+
const appHash = await storeTerm(collection, appTerm);
|
|
123
|
+
// Create abstraction λx.(f x)
|
|
124
|
+
const absTerm = mkAbs(freshVar, appHash);
|
|
125
|
+
const absHash = await storeTerm(collection, absTerm);
|
|
126
|
+
return absHash;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
130
|
+
// Eta Equivalence
|
|
131
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
132
|
+
/**
|
|
133
|
+
* Check if two terms are η-equivalent
|
|
134
|
+
*
|
|
135
|
+
* Two terms f and g are η-equivalent if:
|
|
136
|
+
* - They are the same, or
|
|
137
|
+
* - One η-reduces to the other, or
|
|
138
|
+
* - They both η-expand to equivalent terms
|
|
139
|
+
*/
|
|
140
|
+
export function etaEquivalent(collection, hash1, hash2) {
|
|
141
|
+
return IO.of(async () => {
|
|
142
|
+
// Same hash = definitely equivalent
|
|
143
|
+
if (hash1 === hash2)
|
|
144
|
+
return true;
|
|
145
|
+
// Try reducing both to see if they meet
|
|
146
|
+
const reduced1 = await etaReduceDeep(collection, hash1);
|
|
147
|
+
const reduced2 = await etaReduceDeep(collection, hash2);
|
|
148
|
+
return reduced1 === reduced2;
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Recursively apply η-reduction until no more η-redexes
|
|
153
|
+
*/
|
|
154
|
+
async function etaReduceDeep(collection, termHash) {
|
|
155
|
+
const term = await loadTerm(collection, termHash);
|
|
156
|
+
if (!term)
|
|
157
|
+
return termHash;
|
|
158
|
+
switch (term.tag) {
|
|
159
|
+
case 'Var':
|
|
160
|
+
return termHash;
|
|
161
|
+
case 'Abs': {
|
|
162
|
+
// First try η-reduction at this level
|
|
163
|
+
const etaResult = await etaReduce(collection, termHash).run();
|
|
164
|
+
if (etaResult.isJust) {
|
|
165
|
+
// η-reduced - continue reducing the result
|
|
166
|
+
return etaReduceDeep(collection, etaResult.value);
|
|
167
|
+
}
|
|
168
|
+
// Not an η-redex - recurse into body
|
|
169
|
+
const newBody = await etaReduceDeep(collection, term.body);
|
|
170
|
+
if (newBody === term.body)
|
|
171
|
+
return termHash;
|
|
172
|
+
const newAbs = mkAbs(term.param, newBody);
|
|
173
|
+
return storeTerm(collection, newAbs);
|
|
174
|
+
}
|
|
175
|
+
case 'App': {
|
|
176
|
+
const newFunc = await etaReduceDeep(collection, term.func);
|
|
177
|
+
const newArg = await etaReduceDeep(collection, term.arg);
|
|
178
|
+
if (newFunc === term.func && newArg === term.arg)
|
|
179
|
+
return termHash;
|
|
180
|
+
const newApp = mkApp(newFunc, newArg);
|
|
181
|
+
return storeTerm(collection, newApp);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
186
|
+
// Combined Eta Operations
|
|
187
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
188
|
+
/**
|
|
189
|
+
* Eta-normalize a term by reducing all η-redexes
|
|
190
|
+
*/
|
|
191
|
+
export function etaNormalize(collection, termHash) {
|
|
192
|
+
return IO.of(() => etaReduceDeep(collection, termHash));
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Find all η-redexes in a term
|
|
196
|
+
*/
|
|
197
|
+
export function findEtaRedexes(collection, termHash) {
|
|
198
|
+
return IO.of(async () => {
|
|
199
|
+
const redexes = [];
|
|
200
|
+
await collectEtaRedexes(collection, termHash, redexes);
|
|
201
|
+
return redexes;
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
async function collectEtaRedexes(collection, termHash, redexes) {
|
|
205
|
+
const term = await loadTerm(collection, termHash);
|
|
206
|
+
if (!term)
|
|
207
|
+
return;
|
|
208
|
+
switch (term.tag) {
|
|
209
|
+
case 'Var':
|
|
210
|
+
break;
|
|
211
|
+
case 'Abs': {
|
|
212
|
+
// Check if this is an η-redex
|
|
213
|
+
const isRedex = await isEtaRedex(collection, termHash).run();
|
|
214
|
+
if (isRedex) {
|
|
215
|
+
redexes.push(termHash);
|
|
216
|
+
}
|
|
217
|
+
// Also check body
|
|
218
|
+
await collectEtaRedexes(collection, term.body, redexes);
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
case 'App': {
|
|
222
|
+
await collectEtaRedexes(collection, term.func, redexes);
|
|
223
|
+
await collectEtaRedexes(collection, term.arg, redexes);
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=EtaConversion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EtaConversion.js","sourceRoot":"","sources":["../../../src/ptr/lambda/EtaConversion.ts"],"names":[],"mappings":"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"}
|