Interface
This interface is used to implement the built-in operators and can be used to implement custom operators.
This interface is incomplete and will be changed in v0.4.
Methods
These methods are required to be implemented for some functionalities. If a required method is not implemented, a runtime error will display the function and operator that a method must be implemented for. Default implementations of are not provided so as to avoid correctness bugs.
PAndQ.Interface.Operator
— TypeOperator{O}
Operator{O}()
Return an operator named O
.
Operators are uniquely identified by their name. If possible, an operator should be defined as const o = ℴ = Operator{:o}()
where symbol
(ℴ) == "ℴ"
.
This method is required to instantiate an operator.
PAndQ.Interface.arity
— Functionarity(::Operator)
Return the number of propositions accepted by the Operator
.
This method is required for Lazy
operators.
Examples
julia> Interface.arity(⊤)
0
julia> Interface.arity(¬)
1
julia> Interface.arity(∧)
2
Evaluation
PAndQ.Interface.Evaluation
— TypeEvaluation(::Operator)
A trait to specify the behavior of calling an Operator
.
This method is required to call the given operator.
Examples
julia> @atomize Interface.Evaluation(𝒾)
PAndQ.Interface.Eager
julia> @atomize Interface.Evaluation(¬)
PAndQ.Interface.Lazy
PAndQ.Interface.evaluate
— Functionevaluate(::Operator, ps...)
Define the semantics of the Operator
.
This method is required to normalize
a proposition containing the given operator.
Examples
julia> @atomize Interface.evaluate(¬, ¬p)
p
julia> @atomize Interface.evaluate(→, p, q)
¬p ∨ q
Folding
PAndQ.Interface.Associativity
— TypeAssociativity(::Operator)
A trait to specify the associativity of an Operator
.
This method is required for calling fold
over the operator.
This trait is used internally and does not override how expressions are parsed.
Examples
julia> Interface.Associativity(→)
PAndQ.Interface.Left
julia> Interface.Associativity(←)
PAndQ.Interface.Right
PAndQ.Interface.initial_value
— Functioninitial_value(ℴ::Operator)
Specify a neutral value, v
, of a binary Operator
such that ℴ(v, p) == p
.
To distinguish between an initial value and the absense thereof, return Some(v)
or nothing
, respectively.
This method is required for calling fold
over the operator.
See also ==
.
Examples
julia> Interface.initial_value(∧)
Some(PAndQ.Interface.Operator{:tautology}())
julia> Interface.initial_value(∨)
Some(PAndQ.Interface.Operator{:contradiction}())
julia> Interface.initial_value(↑)
Printing
PAndQ.Interface.print_expression
— Functionprint_expression(io, ::Operator, ps...)
Print the node of a syntax tree containing the Operator
and its propositions.
If a node in a syntax tree is not the root node, it may be necessary to parenthesize it to avoid ambiguity. This context can be obtained using is_root
.
Each proposition should be represented using print_proposition
.
This method is required for calling show(::IO, ::MIME"text/plain, p)
for a proposition p
containing the given operator.
Examples
julia> @atomize Interface.print_expression(stdout, ⊤)
⊤
julia> @atomize Interface.print_expression(stdout, ¬, p)
¬p
julia> @atomize Interface.print_expression(stdout, ∧, p, q)
p ∧ q
PAndQ.Interface.symbol
— Functionsymbol(ℴ::Operator)
Return the Unicode symbol of the Operator
.
If possible, this should be implemented as symbol(::typeof(ℴ)) = "ℴ"
.
This method is required for calling show(::IO, ::MIME"text/plain", ::typeof(ℴ))
.
See also show
.
Examples
julia> Interface.symbol(⊤)
"⊤"
julia> Interface.symbol(¬)
"¬"
julia> Interface.symbol(∧)
"∧"
Utilities
These functions may be necessary or useful for implementing the operator interface.
Evaluation
PAndQ.Interface.Eager
— TypeEager <: Evaluation
A trait to specify that an Operator
is eagerly evaluated.
Eagerly evaluated operators return the expression specified by evaluate
.
Subtype of Evaluation
.
PAndQ.Interface.Lazy
— TypeLazy <: Evaluation
A trait to specify that an Operator
is lazily evaluated.
Lazily evaluated operators return a syntax tree with the operator and its propositions as the root node.
Subtype of Evaluation
.
Associativity
PAndQ.Interface.Left
— TypeLeft <: Associativity
A trait to specify that an Operator
is left-associative.
Subtype of Associativity
.
PAndQ.Interface.Right
— TypeRight <: Associativity
A trait to specify that an Operator
is right-associative.
Subtype of Associativity
.
Printing
PAndQ.Interface.name
— Functionname(::Operator{O})
Return O
, the name of the Operator
.
Examples
julia> Interface.name(⊤)
:tautology
julia> Interface.name(¬)
:not
julia> Interface.name(∧)
:and
PAndQ.Interface.is_root
— Functionis_root(io)
Return a Bool
ean indicating whether the node being printed is the root of a syntax tree.
PAndQ.Interface.parenthesize
— Functionparenthesize(f, io)
Call f
. If not is_root
, print opening and closing parentheses before and after, respectively.
PAndQ.Interface.print_proposition
— Functionprint_proposition(io, p)
Print the given proposition with the IOContext
that :root => false
.
Should be called from print_expression
.
Examples
julia> @atomize print_proposition(stdout, ¬p)
¬p
julia> @atomize print_proposition(stdout, p ∧ q)
(p ∧ q)
Properties
PAndQ.Interface.converse
— Functionconverse(ℴ::Operator)
Return a function such that converse(ℴ)(p, q) == ℴ(q, p)
.
If possible, this method should be implemented to return another Operator
.
See also ==
.
Examples
julia> Interface.converse(∧)
∧
julia> Interface.converse(→)
←
PAndQ.Interface.dual
— Functiondual(ℴ::Operator)
Return a function such that dual(ℴ)(ps...) == ¬(ℴ(map(¬, ps)...))
.
If possible, this method should be implemented to return another Operator
.
Examples
julia> Interface.dual(and)
∨
julia> Interface.dual(imply)
↚
Predicates
PAndQ.Interface.is_associative
— Functionis_associative(ℴ::Operator)
Return a Bool
ean indicating whether the operator has the associative property such that ℴ(ℴ(p, q), r) == ℴ(p, ℴ(q, r))
.
See also ==
.
Examples
julia> Interface.is_associative(∧)
true
julia> Interface.is_associative(→)
false
PAndQ.Interface.is_commutative
— Functionis_commutative(ℴ::Operator)
Return a Bool
ean indicating whether operator has the commutative property such that ℴ(p, q) == ℴ(q, p)
.
See also ==
.
Examples
julia> Interface.is_commutative(∧)
true
julia> Interface.is_commutative(→)
false