I'm pretty sure that it's not constructively provable.
First, note that
¬¬p -> (¬p -> a)
holds for completely arbitrary p
and a
(from ¬¬p
and ¬p
you first obtain proof of falsehood, then by ex falso quodlibet you obtain any a
).
In particular, for any q
,
¬¬p -> ((¬p -> q) /\ (¬p -> ¬q)) // ("lemma")
holds (apply previous statement to a = q
and a = ¬q
).
Now, if your original statement ((¬p -> q) /\ (¬p -> ¬q)) -> p
were true, then you could precompose ¬¬p -> ((¬p -> q) /\ (¬p -> ¬q))
, hence obtaining ¬¬p -> p
. But this is double negation elimination, which is known to not be provable constructively.
Here is the full construction in Scala 3 (somewhat close-ish-ly related to OCaml; The subset of the language used here should be easily translatable to OCaml):
type ¬[A] = A => Nothing // negation
type /\[A, B] = (A, B) // conjunction / product
type Claim[P, Q] = (¬[P] => Q) => (¬[P] => ¬[Q]) => P // your claim
type DoubleNegationElimination[P] = ¬[¬[P]] => P
/** Ex falso quodlibet. */
def efq[X]: Nothing => X = f => f
/** Lemma, as explained above. */
def lemma[P, Q](a: ¬[¬[P]]): (¬[P] => Q) /\ (¬[P] => ¬[Q]) =
val left: ¬[P] => Q = notP => efq(a(notP))
val right: ¬[P] => ¬[Q] = notP => efq(a(notP))
(left, right)
/** This shows that if you could prove your claim for any `P`, `Q`,
* then you would also be able to prove double negation elimination
* for `P`.
*/
def claimImpliesDoubleNegationElimination[P, Q](
c: Claim[P, Q]
): DoubleNegationElimination[P] =
notNotP => {
val (left, right) = lemma[P, Q](notNotP)
c(left)(right)
}
/** This is an (incomplete, because impossible) proof of the double
* negation elimination for any `P`. It is incomplete, because it
* relies on the validity of your original claim.
*/
def doubleNegationElimination[P]: DoubleNegationElimination[P] =
claimImpliesDoubleNegationElimination(claim[P, Unit])
/** There cannot be a constructive proof of this, because otherwise
* we would obtain a constructive proof of `doubleNegationElimination`.
*/
def claim[P, Q]: Claim[P, Q] = ???