Skip to content

Commit

Permalink
Change notation for types, substitutions and instantiations
Browse files Browse the repository at this point in the history
  • Loading branch information
v-- committed Feb 5, 2025
1 parent 2f0965e commit a09eb56
Show file tree
Hide file tree
Showing 23 changed files with 522 additions and 485 deletions.
2 changes: 1 addition & 1 deletion code/notebook/math/lambda_/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@

@pytest.fixture
def dummy_signature() -> LambdaSignature:
return LambdaSignature(base_types={'α', 'β', 'γ'}, constant_terms=set())
return LambdaSignature(base_types={'τ', 'σ', 'ρ'}, constant_terms=set())
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,19 @@ def test_term_instantiation_failure() -> None:


def test_abstraction_annotation_success() -> None:
schema = parse_pure_term_schema('(λx:α.x)', TypingStyle.explicit)
schema = parse_pure_term_schema('(λx:τ.x)', TypingStyle.explicit)
instantiation = LambdaSchemaInstantiation(
variable_mapping={parse_variable_placeholder('x'): parse_variable('x')},
type_mapping={parse_type_placeholder('α'): parse_type(HOL_SIGNATURE, 'ι')}
type_mapping={parse_type_placeholder('τ'): parse_type(HOL_SIGNATURE, 'ι')}
)

expected = parse_term(HOL_SIGNATURE, '(λx:ι.x)', TypingStyle.explicit)
assert instantiate_term_schema(schema, instantiation) == expected


def test_abstraction_annotation_failure() -> None:
with pytest.raises(SchemaInstantiationError, match=r'No specification of how to instantiate the type placeholder α'):
schema = parse_pure_term_schema('(λx:α.x)', TypingStyle.explicit)
with pytest.raises(SchemaInstantiationError, match=r'No specification of how to instantiate the type placeholder τ'):
schema = parse_pure_term_schema('(λx:τ.x)', TypingStyle.explicit)
instantiation = LambdaSchemaInstantiation(
variable_mapping={parse_variable_placeholder('x'): parse_variable('x')},
)
Expand All @@ -104,19 +104,19 @@ def test_typed_instantiation_on_untyped_schema() -> None:
instantiation = LambdaSchemaInstantiation(
variable_mapping={parse_variable_placeholder('x'): parse_variable('x')},
term_mapping={parse_term_placeholder('M'): parse_term(HOL_SIGNATURE, '(λy:ι.y)', TypingStyle.explicit)},
type_mapping={parse_type_placeholder('α'): parse_type(HOL_SIGNATURE, 'ι')}
type_mapping={parse_type_placeholder('τ'): parse_type(HOL_SIGNATURE, 'ι')}
)

instantiate_term_schema(schema, instantiation)


def test_untyped_instantiation_on_typed_schema() -> None:
with pytest.raises(SchemaInstantiationError, match='A typed schema was provided, but the instantiation features untyped terms'):
schema = parse_pure_term_schema('(λx:α.M)', TypingStyle.explicit)
schema = parse_pure_term_schema('(λx:τ.M)', TypingStyle.explicit)
instantiation = LambdaSchemaInstantiation(
variable_mapping={parse_variable_placeholder('x'): parse_variable('x')},
term_mapping={parse_term_placeholder('M'): parse_term(HOL_SIGNATURE, '(λy.y)', TypingStyle.implicit)},
type_mapping={parse_type_placeholder('α'): parse_type(HOL_SIGNATURE, 'ι')}
type_mapping={parse_type_placeholder('τ'): parse_type(HOL_SIGNATURE, 'ι')}
)

instantiate_term_schema(schema, instantiation)
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,18 @@ def test_abstraction_instantiation_failure() -> None:


def test_abstraction_annotation_success() -> None:
schema = parse_pure_term_schema('(λx:α.x)', TypingStyle.explicit)
schema = parse_pure_term_schema('(λx:τ.x)', TypingStyle.explicit)
term = parse_term(HOL_SIGNATURE, '(λx:ι.x)', TypingStyle.explicit)
assert infer_instantiation_from_term(schema, term) == LambdaSchemaInstantiation(
variable_mapping={parse_variable_placeholder('x'): parse_variable('x')},
type_mapping={parse_type_placeholder('α'): parse_type(HOL_SIGNATURE, 'ι')}
type_mapping={parse_type_placeholder('τ'): parse_type(HOL_SIGNATURE, 'ι')}
)


def test_abstraction_annotation_failure() -> None:
with pytest.raises(SchemaInferenceError, match=r'The schema \(λx:α.x\) has a type annotation on its abstractor, but the term \(λx.x\) does not'):
with pytest.raises(SchemaInferenceError, match=r'The schema \(λx:τ.x\) has a type annotation on its abstractor, but the term \(λx.x\) does not'):
infer_instantiation_from_term(
parse_pure_term_schema('(λx:α.x)', TypingStyle.explicit),
parse_pure_term_schema('(λx:τ.x)', TypingStyle.explicit),
parse_pure_term('(λx.x)')
)

Expand Down
28 changes: 14 additions & 14 deletions code/notebook/math/lambda_/parsing/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,10 @@ def test_parsing_valid_type(type_: str, expected: SimpleType) -> None:
schema=[
'ι',
'(ι → o)',
'α',
'(ββ)',
'(ι → (αβ))',
'((ι → α) → β)'
'τ',
'(σσ)',
'(ι → (τσ))',
'((ι → τ) → σ)'
]
)
def test_rebuilding_type_schema(schema: str) -> None:
Expand All @@ -253,11 +253,11 @@ def test_rebuilding_type_schema(schema: str) -> None:

def test_parsing_type_schema_with_regular_parser() -> None:
with pytest.raises(ParsingError) as excinfo:
parse_type(HOL_SIGNATURE, 'α')
parse_type(HOL_SIGNATURE, 'τ')

assert str(excinfo.value) == 'Type placeholders are only allowed in schemas'
assert excinfo.value.__notes__[0] == dedent('''\
1 │ α
1 │ τ
│ ^
'''
)
Expand Down Expand Up @@ -337,10 +337,10 @@ def test_parsing_type_assertion_missing_colon() -> None:

@pytest_parametrize_lists(
rule=[
'(R) ⫢ x: α',
'(R) M: (αβ), N: α ⫢ (MN): β',
'(R) [x: α] M: β ⫢ (λx.M): (αβ)',
'(R) [x: α] M: β ⫢ (λx:α.M): (αβ)'
'(R) ⫢ x: τ',
'(R) M: (τσ), N: τ ⫢ (MN): σ',
'(R) [x: τ] M: σ ⫢ (λx.M): (τσ)',
'(R) [x: τ] M: σ ⫢ (λx:τ.M): (τσ)'
]
)
def test_rebuilding_typing_rules(rule: str) -> None:
Expand All @@ -349,23 +349,23 @@ def test_rebuilding_typing_rules(rule: str) -> None:

def test_parsing_discharge_schema_with_no_name() -> None:
with pytest.raises(ParsingError) as excinfo:
parse_typing_rule(EMPTY_SIGNATURE, '(R) [] x: α ⫢ y: α', TypingStyle.implicit)
parse_typing_rule(EMPTY_SIGNATURE, '(R) [] x: τ ⫢ y: τ', TypingStyle.implicit)

assert str(excinfo.value) == 'Unexpected token'
assert excinfo.value.__notes__[0] == dedent('''\
1 │ (R) [] x: α ⫢ y: α
1 │ (R) [] x: τ ⫢ y: τ
│ ^
'''
)


def test_parsing_discharge_schema_with_no_closing_bracket() -> None:
with pytest.raises(ParsingError) as excinfo:
parse_typing_rule(EMPTY_SIGNATURE, '(R) [x: α y: α ⫢ z: α', TypingStyle.implicit)
parse_typing_rule(EMPTY_SIGNATURE, '(R) [x: τ y: τ ⫢ z: τ', TypingStyle.implicit)

assert str(excinfo.value) == 'Unclosed bracket for discharge schema'
assert excinfo.value.__notes__[0] == dedent('''\
1 │ (R) [x: α y: α ⫢ z: α
1 │ (R) [x: τ y: τ ⫢ z: τ
│ ^^^^^^
'''
)
2 changes: 1 addition & 1 deletion code/notebook/math/lambda_/reduction/strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def reduce_term_once(term: UntypedTerm, strategy: ReductionStrategy) -> UntypedT
reduction = strategy.try_reduce(term)

if reduction is None:
raise ReductionError(f'Cannot β-reduce {reduction}')
raise ReductionError(f'Cannot σ-reduce {reduction}')

return reduction

Expand Down
28 changes: 14 additions & 14 deletions code/notebook/math/lambda_/type_derivation/test_inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,41 @@

# ex:def:type_derivation_tree/i
def test_arrow_intro(dummy_signature: LambdaSignature) -> None:
term = parse_term(dummy_signature, '(λx:α.x)', TypingStyle.explicit)
term = parse_term(dummy_signature, '(λx:τ.x)', TypingStyle.explicit)
assert str(derive_type(term)) == dedent('''\
x: α
x: τ
x _________________ →⁺
(λx:α.x): (αα)
(λx:τ.x): (ττ)
'''
)


def test_nested_arrow_intro(dummy_signature: LambdaSignature) -> None:
term = parse_term(dummy_signature, '(λx:α.(λy:β.x))', TypingStyle.explicit)
term = parse_term(dummy_signature, '(λx:τ.(λy:σ.x))', TypingStyle.explicit)
assert str(derive_type(term)) == dedent('''\
x: α
x: τ
_________________ →⁺
(λy:β.x): (βα)
(λy:σ.x): (στ)
x ______________________________ →⁺
(λx:α.(λy:β.x)): (α → (βα))
(λx:τ.(λy:σ.x)): (τ → (στ))
'''
)


# ex:def:type_derivation_tree/pairs
def test_cons(dummy_signature: LambdaSignature) -> None:
term = parse_term(dummy_signature, '(λx:α.(λy:β.(λf:(α→(β→γ)).((fx)y))))', TypingStyle.explicit)
term = parse_term(dummy_signature, '(λx:τ.(λy:σ.(λf:(τ→(σ→ρ)).((fx)y))))', TypingStyle.explicit)
assert str(derive_type(term)) == dedent('''\
f: (α → (βγ)) x: α
f: (τ → (σρ)) x: τ
____________________________ →⁻
(fx): (βγ) y: β
(fx): (σρ) y: σ
_________________________________________ →⁻
((fx)y): γ
((fx)y): ρ
f _______________________________________________ →⁺
(λf:(α → (βγ)).((fx)y)): ((α → (βγ)) → γ)
(λf:(τ → (σρ)).((fx)y)): ((τ → (σρ)) → ρ)
y ____________________________________________________________ →⁺
(λy:β.(λf:(α → (βγ)).((fx)y))): (β → ((α → (βγ)) → γ))
(λy:σ.(λf:(τ → (σρ)).((fx)y))): (σ → ((τ → (σρ)) → ρ))
x _________________________________________________________________________ →⁺
(λx:α.(λy:β.(λf:(α → (βγ)).((fx)y)))): (α → (β → ((α → (βγ)) → γ)))
(λx:τ.(λy:σ.(λf:(τ → (σρ)).((fx)y)))): (τ → (σ → ((τ → (σρ)) → ρ)))
'''
)
44 changes: 22 additions & 22 deletions code/notebook/math/lambda_/type_derivation/test_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@


def test_assumption_tree(dummy_signature: LambdaSignature) -> None:
assumption = parse_variable_assertion(dummy_signature, 'x: α')
assumption = parse_variable_assertion(dummy_signature, 'x: τ')
tree = assume(assumption)
assert tree.get_context() == {assumption}
assert str(tree) == dedent('''\
x: α
x: τ
'''
)


# ex:def:type_derivation_tree/i
def test_arrow_intro_untyped(dummy_signature: LambdaSignature) -> None:
assumption = parse_variable_assertion(dummy_signature, 'x: α')
assumption = parse_variable_assertion(dummy_signature, 'x: τ')
tree = apply(
ARROW_INTRO_RULE_IMPLICIT,
RuleApplicationPremise(
Expand All @@ -31,16 +31,16 @@ def test_arrow_intro_untyped(dummy_signature: LambdaSignature) -> None:
assert tree.get_context() == set()
assert tree.conclusion.term == combinators.i
assert str(tree) == dedent('''\
x: α
x: τ
x _______________ →⁺
(λx.x): (αα)
(λx.x): (ττ)
'''
)


# ex:def:type_derivation_tree/i
def test_arrow_intro_typed(dummy_signature: LambdaSignature) -> None:
assumption = parse_variable_assertion(dummy_signature, 'x: α')
assumption = parse_variable_assertion(dummy_signature, 'x: τ')
tree = apply(
ARROW_INTRO_RULE_EXPLICIT,
RuleApplicationPremise(
Expand All @@ -51,17 +51,17 @@ def test_arrow_intro_typed(dummy_signature: LambdaSignature) -> None:

assert tree.get_context() == set()
assert str(tree) == dedent('''\
x: α
x: τ
x _________________ →⁺
(λx:α.x): (αα)
(λx:τ.x): (ττ)
'''
)


# ex:def:type_derivation_tree/k
def test_nested_arrow_intro(dummy_signature: LambdaSignature) -> None:
assumption_x = parse_variable_assertion(dummy_signature, 'x: α')
assumption_y = parse_variable_assertion(dummy_signature, 'y: β')
assumption_x = parse_variable_assertion(dummy_signature, 'x: τ')
assumption_y = parse_variable_assertion(dummy_signature, 'y: σ')
tree = apply(
ARROW_INTRO_RULE_IMPLICIT,
RuleApplicationPremise(
Expand All @@ -79,20 +79,20 @@ def test_nested_arrow_intro(dummy_signature: LambdaSignature) -> None:
assert tree.get_context() == set()
assert tree.conclusion.term == combinators.k
assert str(tree) == dedent('''\
x: α
x: τ
_______________ →⁺
(λy.x): (βα)
(λy.x): (στ)
x __________________________ →⁺
(λx.(λy.x)): (α → (βα))
(λx.(λy.x)): (τ → (στ))
'''
)


# ex:def:type_derivation_tree/pairs
def test_cons(dummy_signature: LambdaSignature) -> None:
assumption_f = parse_variable_assertion(dummy_signature, 'f: (α → (βγ))')
assumption_x = parse_variable_assertion(dummy_signature, 'x: α')
assumption_y = parse_variable_assertion(dummy_signature, 'y: β')
assumption_f = parse_variable_assertion(dummy_signature, 'f: (τ → (σρ))')
assumption_x = parse_variable_assertion(dummy_signature, 'x: τ')
assumption_y = parse_variable_assertion(dummy_signature, 'y: σ')
tree = apply(
ARROW_INTRO_RULE_IMPLICIT,
RuleApplicationPremise(
Expand Down Expand Up @@ -126,16 +126,16 @@ def test_cons(dummy_signature: LambdaSignature) -> None:
assert tree.get_context() == set()
assert tree.conclusion.term == pairs.cons
assert str(tree) == dedent('''\
f: (α → (βγ)) x: α
f: (τ → (σρ)) x: τ
____________________________ →⁻
(fx): (βγ) y: β
(fx): (σρ) y: σ
_________________________________________ →⁻
((fx)y): γ
((fx)y): ρ
f _________________________________________ →⁺
(λf.((fx)y)): ((α → (βγ)) → γ)
(λf.((fx)y)): ((τ → (σρ)) → ρ)
y ____________________________________________ →⁺
(λy.(λf.((fx)y))): (β → ((α → (βγ)) → γ))
(λy.(λf.((fx)y))): (σ → ((τ → (σρ)) → ρ))
x _______________________________________________________ →⁺
(λx.(λy.(λf.((fx)y)))): (α → (β → ((α → (βγ)) → γ)))
(λx.(λy.(λf.((fx)y)))): (τ → (σ → ((τ → (σρ)) → ρ)))
'''
)
8 changes: 4 additions & 4 deletions code/notebook/math/lambda_/type_systems/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@


# These rules are distinct
ARROW_INTRO_RULE_IMPLICIT = parse_typing_rule(EMPTY_SIGNATURE, '(→⁺) [x: α] M: β ⫢ (λx.M): (αβ)', TypingStyle.implicit)
ARROW_INTRO_RULE_EXPLICIT = parse_typing_rule(EMPTY_SIGNATURE, '(→⁺) [x: α] M: β ⫢ (λx:α.M): (αβ)', TypingStyle.explicit)
ARROW_INTRO_RULE_IMPLICIT = parse_typing_rule(EMPTY_SIGNATURE, '(→⁺) [x: τ] M: σ ⫢ (λx.M): (τσ)', TypingStyle.implicit)
ARROW_INTRO_RULE_EXPLICIT = parse_typing_rule(EMPTY_SIGNATURE, '(→⁺) [x: τ] M: σ ⫢ (λx:τ.M): (τσ)', TypingStyle.explicit)

# These rules are identical, but belong to different classes
ARROW_ELIM_RULE_IMPLICIT = parse_typing_rule(EMPTY_SIGNATURE, '(→⁻) M: (αβ), N: α ⫢ (MN): β', TypingStyle.implicit)
ARROW_ELIM_RULE_EXPLICIT = parse_typing_rule(EMPTY_SIGNATURE, '(→⁻) M: (αβ), N: α ⫢ (MN): β', TypingStyle.explicit)
ARROW_ELIM_RULE_IMPLICIT = parse_typing_rule(EMPTY_SIGNATURE, '(→⁻) M: (τσ), N: τ ⫢ (MN): σ', TypingStyle.implicit)
ARROW_ELIM_RULE_EXPLICIT = parse_typing_rule(EMPTY_SIGNATURE, '(→⁻) M: (τσ), N: τ ⫢ (MN): σ', TypingStyle.explicit)
2 changes: 1 addition & 1 deletion code/notebook/support/test_unicode.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def test_is_latin_string_capitaliation(string: str = 'abc') -> None:
assert xnor(Capitalization.mixed in cap, is_latin_string(mixed, capitalization=cap))


def test_is_greek_string_capitaliation(string: str = 'αβγ') -> None:
def test_is_greek_string_capitaliation(string: str = 'τσρ') -> None:
lower = string.lower()
upper = string.upper()
mixed = string.title()
Expand Down
2 changes: 1 addition & 1 deletion code/notebook/support/unicode.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def is_latin_string(string: str, capitalization: Capitalization) -> bool:
def is_greek_string(string: str, capitalization: Capitalization) -> bool:
return all(
('Α' <= c <= 'Ω' if Capitalization.upper in capitalization else False) or
('α' <= c <= 'ω' if Capitalization.lower in capitalization else False)
('τ' <= c <= 'ω' if Capitalization.lower in capitalization else False)
for c in string
)

Expand Down
4 changes: 2 additions & 2 deletions figures/ex__def__propositional_formula_ast.tex
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
[
\( \synwedge \)
[\( \synq \)]
[\( \syn r \)]
[\( \synr \)]
]
]
\end{forest}
Expand All @@ -35,7 +35,7 @@
[\( \synp \)]
[\( \synq \)]
]
[\( \syn r \)]
[\( \synr \)]
]
\end{forest}
\end{document}
Loading

0 comments on commit a09eb56

Please sign in to comment.