It's interesting to me that different people's intuitions were so different on this. Different models are helpful with different examples, and nobody in the thread mentioned the connection between intuitionistic logic and programming language semantics, which for this example I found very helpful.
In the programming language model, $$(A\to(B\lor C))\to((A\to B)\lor(A\to C))$$ is the type of a function $f$ which is given a value $in$ of type $$A\to(B\lor C)$$ and which transforms it into a value $out$ of type $$(A\to B)\lor(A\to C).$$ How might we implement such a function $f$?
An experienced computer programmer will think something like this:
I would need to produce a function that turns $A$ into $B$. I can't do that because all I have is a function that turns $A$ into $B\lor C$ and it might not give me the $B$ I need.
That's the intuition. The intuition is a shortcut for the following thought process.
In code, our function $f$ will look like this:
def f in = out where -- `in` has type A → (B ∨ C)
out = ??? -- `out` should have type (A → B) ∨ (A → C)
$\def\lt{\mathtt{Left}\ }\def\rt{\mathtt{Right}\ }$
A value of type $(A\to B)\lor(A\to C)$ must have the form $\lt out_L$ where $out_L$ has type $A\to B$, or $\rt out_R$ where $out_R$ has type $A\to C$. Those are the only two choices. Let's try the first one:
def f in = out where -- `in` has type A → (B ∨ C)
out = Left outL -- `outL` should have type A → B
Since outL
has type $A\to B$, it is a function that takes a value of type $A$ and turns it into a value of type $B$:
def f in = out where -- `in` has type A → (B ∨ C)
out = Left outL
outL a = ??? -- we want to produce a value of type B
Where is $out_L$ going to get a value of type $B$? The only tools it has available are $in$ (of type $A\to(B\lor C)$) and $a$ (of type $A$) and there is only one thing it can do with these: it must give the argument $a$ to the function $in$, producing a result of type $B\lor C$:
def f in = out where -- `in` has type A → (B ∨ C)
out = Left outL
outL a = ?? in a ?? -- `in a` has type B ∨ C
-- we want to produce a value of type B
The in a
expression produces a value of type $B\lor C$. A value of type $B\lor C$ looks either like $\lt b$ or like $\rt c$, so we need a case
expression to handle the two cases.
def f in = out where -- `in` has type A → (B ∨ C)
out = Left outL
outL a = case in a of -- we want to produce a value of type B
Left b -> ???
Right c -> ???
In the $\lt b$ case it's easy to see how to proceed: just return the $b$:
def f in = out where -- `in` has type A → (B ∨ C)
out = Left outL
outL a = case in a of -- we want to produce a value of type B
Left b -> b -- … and we did!
Right c -> ???
In the $\rt c$ case there's no way to proceed, because $out_L$ has available a value $c$ of type $C$, but it still needs to produce a value of type $B$ and it has no way to get one. There is no way to complete the implementation.
Perhaps we made a mistake back at the beginning when we chose to define out = Left outL
? Would out = Right outR
work better? No, the problem will be exactly the same:
def f in = out where -- `in` has type A → (B ∨ C)
out = Right outR
outR a = case in a of -- we want to produce a value of type C
Left b -> ??? -- … but we don't have one
Right c -> c
This exhausts the possibilities. There is no way to implement $f$.
The points I want to make here are not only that programmers can and do acquire this sort of intuition for what can't be implemented and why not, but also that they can convert the intuition into an argument that doesn't rely on the intuition alone. Once the intuition is turned a detailed argument, the Curry-Howard correspondence can be used to convert the failed implementation directly to an LJ sequent calculus proof or analytic tableau proof that the statement is invalid.
[ Addendum: Note by the way that the reverse implication, which is intuitionistically valid, is easy to prove and just as easy to construct a program:
def fINV out a = -- fINV has type ((A→B)∨(A→C))→(A→(B∨C))
case out of Left outL -> Left (outL a) -- outL has type A→B
Right outR -> Right (outR a) -- outR has type A→C
and again the Curry-Howard correspondence converts the program into a proof or vice-versa. ]