abstract type Prop end

abstract type ‚ä§ <: Prop end
abstract type ‚ä• <: Prop end

abstract type ‚Üí{A, B} <: Prop where {A <: Prop, B <: Prop} end

abstract type ùí´ <: Prop end

ùïÉ = []

macro variable(A) :(abstract type $A <: ùí´ end; push!(ùïÉ, $A)) end

@variable P; @variable Q; @variable R;

‚Üí(::Type{A}, ::Type{B}) where {A <: Prop, B <: Prop} = ‚Üí{A, B}
¬¨(::Type{A}) where {A <: Prop} = A ‚Üí ‚ä•

Base.show(io::IO, ::Type{‚Üí{A, B}}) where {A <: Prop, B <: Prop} = print(io, "($A ‚Üí $B)")

function Base.rand(::Type{Prop}; œÅ::Float64 = 0.6)
    if rand() ‚â§ œÅ
        rand(Bool) ? ‚Üí{rand(Prop), rand(Prop)} : ¬¨(rand(Prop))
    else
        rand(ùïÉ)
    end
end

fst(::Type{‚Üí{A, B}}) where {A <: Prop, B <: Prop} = A
snd(::Type{‚Üí{A, B}}) where {A <: Prop, B <: Prop} = B