Assume in lean 4 - lean

A lot of proofs in Lean 3 were structured via the assume syntax e.g.
theorem WetTheorem :
forall Rain Hydrant Wet: Prop,
(Rain ∨ Hydrant) → -- raining or hydrant on;
(Rain → Wet) → -- if raining then wet;
(Hydrant → Wet) → -- if hydrant on then wet;
Wet -- then wet
:=
begin
-- setup
assume Rain Hydrant Wet,
assume RainingOrHydrantRunning: (Rain ∨ Hydrant),
assume RainMakesWet: (Rain → Wet),
assume HydrantMakesWet: (Hydrant → Wet),
-- the core of the proof
cases RainingOrHydrantRunning with raining running,
show Wet, from RainMakesWet raining,
show Wet, from HydrantMakesWet running,
end
I was unable find a similar reference section for tactics in lean 4 like in 3, and it seems assume has been dropped. What would be the general method of converting a lean 3 proof with assume into a lean 4 without it?

assume in tactic mode can be replaced by intro with a type ascription in lean 4, so your entire code can be written as follows
theorem WetTheorem :
forall Rain Hydrant Wet: Prop,
(Rain ∨ Hydrant) → -- raining or hydrant on;
(Rain → Wet) → -- if raining then wet;
(Hydrant → Wet) → -- if hydrant on then wet;
Wet -- then wet
:=
by
-- setup
intro Rain Hydrant Wet
intro (RainingOrHydrantRunning : (Rain ∨ Hydrant))
intro (RainMakesWet: (Rain → Wet))
intro (HydrantMakesWet: (Hydrant → Wet))
-- the core of the proof
cases RainingOrHydrantRunning
case inl raining =>
exact RainMakesWet raining
case inr running =>
exact HydrantMakesWet running

Related

Is Last a free monoid?

The free monoids are often being regarded as "list monoids". Yet, I am interested in other possible structures which might give us free monoids.
Firstly, let us go over the definition of free monoids. I have never quite understood how is it possible to define a free monoid as a structure which abides by monoid laws and nothing else. How do we prove that something abides by no rules but stated above? Or is this just an intuition?
Anyway, we are going to speak functors. If some monoid is free, we got it with a free functor. It is obvious that a list comes in quite handy here:
free :: Set -> Mon
free a = ([a], (++), [])
Yet, one might come up with several others. For example, here is one for Last of Data.Monoid:
freeLast :: Set -> Mon
freeLast a = (Last a, (<>) :: Last a -> Last a -> Last a, Last Nothing)
So, does this functor make Last a free monoid? More generally, if there is a law-abiding instance for Monoid (T a), is T a free monoid?
Here's one way to understand a free monoid: If somebody gives you a value, how much can you deduce about how it was created? Consider an additive monoid of natural numbers. I give you a 7 and ask you how I got it. I could have added 4+3, or 3+4, or 2+5, etc. There are many possibilities. This information was lost. If, on the other hand, I give you a list [4, 3], you know it was created from singletons [4] and [3]. Except that maybe there was a unit [] involved. Maybe it was [4]<>[3]<>[] or [4]<>[]<>[]<>[3]. But it definitely wasn't [3]<>[4].
With a longer list, [1, 2, 3], you have additional options ([1]<>[2]) <> [3], or [1] <> ([2]<>[3]), plus all possible insertions of the empty list. So the information you lose follows the unit laws and associativity, but nothing else. A free monoid value remembers how it was created, modulo unit laws and associativity.
For the sake of example, let's take non-negative Integer numbers, i.e. 0,1,2,.... How many monoids can we make?
Defining mempty = 0 and (<>) = (+). You can proof easily that this is a monoid.
Defining mempty = 1 and (<>) = (*). Again, This is a monoid (Prove it, it is easy)
The two monoids defined above, are called additive and multiplicative monoids over Natural numbers. They are different in structure, for example, the element 0 in the multiplicative monoid, behaves totally different than any other element in the additive monoid, hence there is something inner to Natural numbers, that makes this monoids different (hold this assertion till the next paragraph).
There exists a third monoid we can create, let's call it concatenation monoid.
Defining mempty = no-action and (<>) = glue one integer beside the other.
As an example, 3 <> mempty = 3 and 3 <> 2 = 32. Notice, that the fact that elements, are natural numbers is not relevant here. If instead of Natural, we take Rationals, or what ever symbols you like, the monoid would be exactly the same thing.(* read foot note) Hence, there is nothing inner to the underlying set that makes the monoid different to others. Thats why, the monoid is free because it doesn't depend on arithmetic rules of the Naturals, nor any other rule aside from monoid ones.
And this is the only way to build a monoid freely, not depending on the inner rules of the underlying set. Of course, concatenation is expressed as lists in haskell.
Note: The only important bit is that they share the same number of elements. For example, the free monoid with 3 elements a, b and c would be any arbitrary concatenation of those three, but you can choose what ever symbol: 1, 2, 3 or α, β, γ ... and the monoid would be the very same thing
Firstly, let us go over the definition of free monoids. I have never quite understood how is it possible to define a free monoid as a structure which abides by monoid laws and nothing else. How do we prove that something abides by no rules but stated above? Or is this just an intuition?
Let me illustrate the purpose of free monoids.
If I tell you there is a monoid, with some elements a, b, c, what can you deduce from that?
We can find more elements of that monoid by writing expressions involving the generators a, b, c and the monoid operations (+) and 0 (aka. (<>) and mempty). (cf. Definition 1, in the second half of this answer.)
We can use the monoid laws to prove that some expressions denote the same element: we can prove equations such as ((a + 0) + b) = (a + b). (Definition 2.) In fact, equations we can prove with just that knowledge are equations which hold in any monoid, for any values a, b, c. (Theorem 1.)
What about equations we can't prove from just the monoid laws? For example, we can't prove (a + b) = (b + a). But we can't prove its negation either, (a + b) /= (b + a), if we only know the monoid laws. What does that mean? It turns out that that equation holds in some monoids (e.g., commutative monoids), but not in others: for example, pick a monoid where x + y = y for almost all x and y (this is the Last monoid in Haskell), if we choose distinct a and b, then (a + b) /= (b + a).
But that was just one example. What can we say in general about equations that we cannot prove from just the monoid laws? The free monoid offers a definitive answer, in fact, a universal counterexample: unprovable equations are false in the free monoid (generated by a, b, c). In other words, we can prove an equation e = f using just the monoid laws if and only if it is true in the free monoid (emphasis on "if"). (Theorem 2.) This corresponds to the intuition that the free monoid "only abides by the monoid laws and nothing else".
So, does this functor make Last a free monoid? More generally, if there is a law-abiding instance for Monoid (T a), is T a free monoid?
The Last monoid is not free because it makes more equations true than what you can actually prove purely from the monoid laws. See other answer:
forall (t :: Type) (x, y :: t).
Last (Just x) <> Last (Just y) === Last (Just y)
Here's a sketch of how to formalize the above.
Definition 1. The set of monoidal expressions generated by (some atomic symbols) A, B, C is defined by the grammar:
e ::=
| A | B | C -- generators
| e + e -- binary operation (<>)
| 0 -- identity (mempty)
Given any "suitable monoid", that is to say, a monoid (M, (+), 0) with some chosen elements a, b, c in M (which don't have to be distinct), an expression e denotes an element eval e in M.
Definition 2. An equation is a pair of expressions, written e ~ f. The set of provable equations is the smallest set of equations ("smallest" when ordered by inclusion) satisfying the following:
It includes the monoid laws: (e + 0) ~ e, (0 + e) ~ e, ((e + f) + g) ~ (e + (f + g)) are provable.
It is an equivalence relation (viewing a set of tuples as a relation): for example, for reflexivity, e ~ e is provable.
It is a congruence relation: if e ~ f is provable then (g + e) ~ (g + f) and (e + g) ~ (f + g) are provable.
(The idea of that definition is that the assertion "e ~ f is provable" holds if and only if it can be deduced by "applying" those rules. "Smallest set" is a conventional method to formalize that.)
The definition of "provable equations" may seem arbitrary. Are those the right rules to define "provability"? Why these three rules in particular? Notably, the congruence rule may not be obvious in a first attempt at giving such a definition. This is the point of the following theorems, soundness and completeness. Add a (non-redundant) rule, and we lose soundness. Remove a rule, and we lose completeness.
Theorem 1. (Soundness) If e ~ f is provable, then eval e = eval f in any "suitable monoid" M.
Theorem 2. (Completeness) If e ~ f is not provable, then their denotations differ in F, eval e /= eval f, where F is the free monoid generated by A, B, C.
(Soundness is much easier to prove than completeness. Exercises for the reader.)
This completeness theorem is a characterization of the free monoid: any other monoid F which keeps the statement of the theorem true is isomorphic to the free monoid (technically, this requires both completeness and an assumption that the denotation function eval : Expr -> M is surjective). That is why we may say "the free monoid" instead of "the monoid of lists"; that practice is most accurate in contexts where the representation does not matter ("up to isomorphism").
In fact, completeness is trivial if you define "the free monoid" as the quotient of monoidal expressions by the equivalence relation "_ ~ _ is provable". The hard work actually resides in a separate proof, that this monoid is isomorphic to the monoid of lists.
Here is another law that Last satisfies:
forall (t :: Type) (x, y :: t).
Last (Just x) <> Last (Just y) === Last (Just y)
Since it satisfies another law, it must not be the free Monoid.

Interesting operators in Haskell that obey modal axioms

I was just looking at the type of map :: (a -> b) -> [a] -> [b] and just the shape of this function made me wonder whether we could see the list forming operator [ ] as obeying various axioms common to normal modal logics (e.g, T, S4, S5, B), since we seem to have at least the K-axiom of normal modal logics, with [(a -> b)] -> [a] -> [b].
This leads to my question: are there familiar, interesting operators or functors in Haskell which have the syntax of modal operators of a certain kind, and which obey the axioms common to normal modal logics (i.e, K, T, S4, S5 and B)?
This question can be sharpened and made more specific. Consider an operator L, and its dual M. Now the question becomes: are there any familiar, interesting operators in Haskell with some of the following properties:
(1) L(a -> b) -> La -> Lb
(2) La -> a
(3) Ma -> L(M a)
(4) La -> L(L a)
(5) a -> L(M a)
It would be very interesting to see some nice examples.
I've thought of a potential example, but it would be good to know whether I am correct: the double negation translation with L as not not and M as not. This translation takes every formula a to its double negation translation (a -> ⊥) -> ⊥ and, crucially, validates axioms (1)-(4), but not axiom (5). I asked a question here https://math.stackexchange.com/questions/2347437/continuations-in-mathematics-nice-examples and it seems the double negation translation can be simulated via the continuation monad, the endofunctor taking every formula a to its double negation translation (a -> ⊥) -> ⊥. There Derek Elkins notes the existence of a couple of double negation translations corresponding, via the Curry-Howard isomorphism, to different continuation-passing style transforms, e.g. Kolmogorov's corresponds to the call-by-name CPS transform.
Perhaps there are other operations that can be done in the continuation monad via Haskell which can validate axioms (1)-(5).
(And just to eliminate one example: there are clear relations between so-called Lax logic https://www.sciencedirect.com/science/article/pii/S0890540197926274 and Monads in Haskell, with the return operation obeying the laws of the modal operator of this logic (which is an endofunctor). I am not interested so much in those examples, but in examples of Haskell operators which obey some of the axioms of modal operators in classical normal modal logics)
Preliminary note: I apologise for spending a good chunk of this answer talking about Propositional Lax Logic, a topic you are very familiar with and not too interested in as far as this question is concerned. In any case, I do feel this theme is worthy of broader exposure -- and thanks for making me aware of it!
The modal operator in propositional lax logic (PLL) is the Curry-Howard counterpart of Monad type constructors. Note the correspondence between its axioms...
DT: x -> D x
D4: D (D x) -> D x
DF: (x -> y) -> D x -> D y
... and the types of return, join and fmap, respectively.
There are a number of papers by Valeria de Paiva discussing intuitionistic modal logics and, in particular, PLL. The remarks about PLL here are largely based on Alechina et. al., Categorical and Kripke Semantics for Constructive S4 Modal Logic (2001). Interestingly, that paper makes a case for the PLL being less weird than it might seem at first (cf. Fairtlough and Mendler, Propositional Lax Logic (1997): "As a modal logic it is special because it features a single modal operator [...] that has a flavour both of possibility and necessity"). Starting with CS4, a version of intuitionistic S4 without distribution of possibility over disjunction...
B stands for box, and D for diamond
BK: B (x -> y) -> (B x -> B y)
BT: B x -> x
B4: B x -> B (B x)
DK: B (x -> y) -> (D x -> D y)
DT: x -> D x
D4: B (B x) -> B x
... and adding x -> B x to it causes B to become trivial (or, in Haskell parlance, Identity), simplifying the logic to PLL. That being so, PLL can be regarded as a special case of a variant of intuitionistic S4. Furthermore, it frames PLL's D as a possibility-like operator. That is intuitively appealing if we take D as the counterpart to Haskell Monads, which often do have a possibility flavour (consider Maybe Integer -- "There might be an Integer here" -- or IO Integer -- "I will get an Integer when the program is executed").
A few other possibilities:
At a glance, it seems the symmetrical move of making D trivial leads us to something very much like ComonadApply. I say "very much like" largely due to the functorial strength of Haskell Functors, the matter being that x /\ B y -> B (x /\ y) is an awkward thing to have if you are looking for a conventional necessity modality.
Kenneth Foner's Functional Pearl: Getting a Quick Fix on Comonads (thanks to dfeuer for the reference) works towards expressing intuitionistic K4 in Haskell, covering some of the difficulties along the way (including the functorial strength issue mentioned above).
Matt Parsons' Distributed Modal Logic offers a Haskell-oriented presentation of intuitionistc S5 and an interpretation of it, originally by Tom Murphy VII, in terms of distributed computing: B x as a x-producing computation that can be run anywhere on a network, and D x as an address to a x somewhere on it.
Temporal logics can be related via Curry-Howard to functional reactive programming (FRP). Suggestions of jumping-off points include de Paiva and Eades III, Constructive Temporal Logic, Categorically (2017), as well as this blog post by Philip Schuster alongside this interesting /r/haskell thread about it.

A categorical analogue for some applicative infrastructure I used?

I've been reading a bit about the category theoric interpretation of Haskell Applicative functors: apparently, they can be interpreted in category theoretic terms as either lax closed functors or lax monoidal functors (depending on who you ask, it seems), and this made me wonder about the following.
A while ago, I wrote a paper (together with Ilya Sergey and our advisors Frank Piessens and Dave Clarke) about a recursion primitive for "effect recursion" in DSLs using Applicative functors, intended mainly for use in parser libraries. We found out that we needed a few quite special constructors that seem like they might be generalisable (somehow). In summary, what I'm asking is: are some of the below constructions somehow connected to category theory and if so, how?
Note that I will write p ◦ q for the composition of two applicative functors p and q.
Here is a list of the primitives we needed along the way:
afix: an effect recursion primitive.
We really wanted a recursion primitive that looked like this:
afix :: (p a → p a) → p a
However, this was unimplementable for the more complex interpretations of p that we needed. Instead, we ended up with the following:
afix :: (∀ q. Applicative q ⇒ p (q a) → p (q a)) → p a
Apparently, wrapping values of the recursive occurrence in this parametrically quantified applicative functor q enforced a kind of value-effect separation in the function that we take the fixpoint of. Apparently, this was sufficient to make our more complex functions work.
Deeper in the implementation, we needed a sort of coapplicative operator that looks like this:
coapp0 :: (p a → p b) → p (a → b)
However, requiring this as a general operator for p, seems like it would have restricted us to only trivial applicative functors p. Instead, we noticed that we could make do with the following, which was implementable:
coapp :: Applicative p ⇒ (∀ q . Applicative q ⇒ (p ◦ q) a → (p ◦ q) b) → p (a → b)
So in summary: is any of the above somehow familiar-looking from a category-theoretic point of view? Specifically, the restriction over functions of type ∀ q . Applicative q ⇒ (p ◦ q) a → (p ◦ q) b rather than p a -> p b seems like it might be fundamental somehow? Are there any links that might help us make more sense of this stuff than we were able to do in the past?
There are more details in the paper about the above and how we used it, in case anyone is interested.

Is it usual for interaction nets to leave piles of redundant fans?

I'm compiling lambda calculus terms to interaction nets in order to evaluate them using Lamping's abstract algorithm. In order to test my implementation, I used this church-number division function:
div = (λ a b c d . (b (λ e . (e d)) (a (b (λ e f g . (e (λ h . (f h g)))) (λ e . e) (λ e f . (f (c e)))) (b (λ e f . e) (λ e . e) (λ e . e)))))
Dividing 4 by 4 (that is, (λ k . (div k k)) (λ f x . (f (f (f (f x)))))), I get this net:
(Sorry for the awful rendering. λ is a lambda, R is root, D is a fan, e is eraser.)
Reading this term back, I get the church number 1, as expected. But this net is very inflated: it has a lot of fans and erasers that serve no obvious purpose. Dividing bigger numbers is even worse. Here is div 32 32:
This again reads back as one, but here we can see an even longer tail of redundant fan nodes. My question is: is this an expected behavior of interaction needs when reducing that particular term or is this a possible bug on my implementation? If this isn't a bug, is there any way around that?
Yes, it is usual (but there are techniques to lessen its presence)
Abstracting from some details of your implementation with Interaction Nets,
and also from your hypothesis of soundness of the abstract algorithm for your div,
everything seems just fine to me.
No further interaction can be applied to the output you show, in spite of chi's claim, because none of the pairs D-e can interact through their principal port.
This latter kind of reduction rule (that is not allowed by IN framework) may improve efficiency and it is also sound in some particular cases.
Basically, the involved fan must not have any "twin", i.e. there must exists no D' in the net such that eventually the annihilation D-D' can happen.
For more details, look at The optimal implementation of functional programming language, chapter Safe nodes (which is available online!), or at the original paper from which that came:
Asperti, Andrea, and Juliusz Chroboczek. "Safe Operators: Brackets Closed Forever Optimizing Optimal λ-Calculus Implementations." Applicable Algebra in Engineering, Communication and Computing 8.6 (1997): 437-468.
Finally, the read-back procedure must be intended not as some sort of external cost for your reduction precedure, but rather as a deferred cost of computing duplication and erasure.
As you notice, such a cost is rarely negligible, so if you want to test efficiency in a real-world scenario, always sum up both sharing reduction and read-back reduction.

Encoding ExistentialQuantification with RankNTypes

I've read in a few places claims that equivalent functionality to ExistentialQuantification can be had using RankNTypes. Could someone provide an example of why this is or is not possible?
Normally, all type variables in Haskell are implicitly universally quantified at the outermost scope of the type. RankNTypes allows a universal quantifier forall to appear nested, e.g. the type forall a b. (a -> a) -> b -> b is very different from forall b. (forall a. a -> a) -> b -> b.
There is a sense in which types on the left side of a function arrow are logically "negated", in roughly the same sense that (->) is logical implication. Logically, the universal and existential quantifiers are related by a De Morgan duality: (∃x. P(x)) is equivalent to ¬(∀x. ¬P(x)), or in other words "there exists an x such that P(x)" corresponds to "it is not the case that, for all x, P(x) is false".
So a forall on the left of a function arrow is "negated" and behaves like an existential. If you put the whole thing to the left of another function arrow it's double-negated and behaves as a universal quantifier again, modulo some fiddly details.
The same idea of negation applies to values as well, so to encode the type exists x. x we want:
forall x. in contravariant (negated) position
a value of that type x in covariant (positive) position.
Since the value must be inside the scope of the quantifier, our only choice is double-negation--a CPS transform, basically. To avoid restricting things otherwise, we'll then universally quantify over the type on the right of the function arrows. So exists x. x is translated to forall r. (forall x. x -> r) -> r. Compare the placement of the types and quantifiers here to the requirements above to verify that it meets the requirement.
In more operational terms this just means that given a function with the above type, because we give it a function with a universally quantified argument type, it can apply that function to any type x it likes, and since it has no other way of getting a value of type r we know it will apply that function to something. So x will refer to some type, but we don't know what--which is basically the essence of existential quantification.
In more practical, day to day terms, any universally quantified type variable can be regarded as existential if you're looking at it from the "other side" of a function type. Because the unification performed as part of type inference transcends quantifier scope, you can sometimes end up in a situation where GHC would have to unify a type variable in an outer scope with a quantified type from a nested scope, which is how you get compiler errors about escaping types and skolems and whatnot, the latter (I assume) being related to Skolem normal form.
The way this relates to data types using existentials is that while you can declare a type like this:
data Exists = forall a. Exists a
That represents an existential type, to get at the "existential type" you need to unwrap it by pattern matching:
unexist :: Exists -> r
unexist (Exists x) = foo x
But if you consider what the type of foo would have to be in this definition, you end up with something like forall a. a -> r, which is equivalent to the CPS-style encoding above. There's a close relationship between CPS transforms and Church encoding of data types, so the CPS form can also be seen as a reified version of the pattern match.
Finally, relating things back to logic--since that's where the term "existential quantifier" comes from--note that, if you think of being left of an arrow as negation and kinda squint to ignore the forall r. ... CPS cruft, these encodings of existential types are exactly the same thing as the De Morgan dualized form ¬(∀x. ¬P(x)) that was the starting point. So these really all are just different ways of looking at the same concept.
Something I've found useful to understand C. A. McCann's point that the left hand side of the function arrow is "negated" is to look at this from the point of view of game semantics. For example, here is a very simple game semantics for first-order logic (stated very informally):
There are two players, #1 and #2
There are two roles: Proponent and Opponent.
Player #1 is the initial Proponent, Player #2 the initial Opponent.
For a proposition ∀x.A, Opponent chooses a t and we play A[x := t] (A with all free instances of x replaced with t).
For a proposition A && B, Opponent chooses to oppose one of the conjuncts.
For a proposition not A, the players switch roles and play A.
For an atomic proposition, we consult its truth value; Proponent wins iff it's true, Opponent wins iff it's false.
The point of games like these is that a proposition is logically valid iff Player #1 (the initial Proponent) has a winning strategy for the corresponding game, i.e., if Player #1 has a winning move no matter what choices Player #2 makes.
Note the role-switch in the negation rule. The effect of that rule should be intuitive.
Because of the propositions-as-types correspondence this can be translated to type theory. Let's reformulate the game in terms of types formed in terms of some set of atoms, ∀, type variables, →, ⊤ and ⊥:
Two players; but we'll call them Runner and Crasher
Runner is initial Proponent, Crasher is initial Opponent
∀x.a: Opponent picks an atom P, and we play a[x := P] (a with all free instances of x replaced by P]
a → b: Proponent chooses whether to oppose a (role switch) or propose b.
Atomic type: Proponent wins iff type is inhabited, Opponent wins iff it's uninhabited. (I assume we've determined that beforehand for all atoms; also that ⊤ is inhabited and ⊥ is not.)
Note that in the rule for a → b, if Proponent picks a then the roles switch: the initial Proponent must become the Opponent for a. This corresponds to the fact that the left hand side of the arrow is "negated". (The idea is that ⊥ → b is inhabited no matter what b may be, so if the Proponent of a → b has a winning strategy to oppose a, then a → b must be inhabited, so its Proponent wins.)
Again, the idea is that a type is inhabited iff Runner has a winning strategy, and uninhabited iff Crasher has a winning strategy.
Example game: ∀r. (∀a. (a → Int) → a → r) → r
Opponent (Crasher) picks r := ⊥: (∀a. (a → Int) → a → ⊥) → ⊥
Proponent (Runner) chooses to oppose the antecedent: ∀a. (a → Int) → a → ⊥
Opponent (Runner) picks a := String: (String → Int) → String → ⊥
Proponent (Crasher) chooses to oppose the antecendent: String → Int
Proponent (Runner) chooses to propose the consequent: Int
Int is inhabited; Proponent (Runner) wins.
Suppose we added a rule for ∃. The rule would have to be like this:
∃x.a: Proponent picks x := P, and we play a[x := P]
Now, we can use this to analyze McCann's assertion that ∀r. (∀a. a → r) → r is equivalent to ∃a.a by analyzing corresponding game trees. I'm not going to do show the whole game tree (or carefully prove the equivalence, really), but I'll show two illustrative games:
First game: ∃a.a
Proponent (Runner) picks a := ⊤.
⊤ is inhabited; Proponent (Runner) wins.
Second game: ∀r. (∀a. a → r) → r
Opponent (Crasher) picks r := ⊥: (∀a. a → ⊥) → ⊥
Proponent (Runner) chooses to oppose the antecedent: ∀a. a → ⊥
Opponent (Runner) chooses a := ⊤: ⊤ → ⊥
Proponent (Crasher) loses because they must choose between opposing ⊤ or proposing ⊥.
Now, the informal observation I'm going to make here is that in both games Runner is the one who gets to pick the type to use for a. The equivalence between ∃a.a and ∀r. (∀a. a → r) → r really comes down to this: there is no strategy that allows Crasher to be the one who picks for a.

Resources