Curry's paradox (named after the same person as the present programming language) is a construction possible in a faulty logic that allows one to prove anything.
I know nothing about logic, but how hard can it be?
module Main where
import Data.Void
import Data.Function
data X = X (X -> Void)
x :: X
x = fix \(X f) -> X f
u :: Void
u = let (X f) = x in f x
main :: IO ()
main = u `seq` print "Done!"
It certainly does loop. (How does GHC know?!)
% ghc -XBlockArguments Z.hs && ./Z
[1 of 1] Compiling Main ( Z.hs, Z.o )
Linking Z ...
Z: <<loop>>
- Is this a faithful translation? Why?
- Can I do the same without
fix
or recursion? Why?
The encoding of Curry's paradox looks more like this:
X
can indeed be read as the sentence "ifX
is true, then there is a contradiction", or equivalently, "X
is false".But using
fix
to proveX
is not really meaningful, becausefix
is blatantly incorrect as a reasoning principle. Curry's paradox is more subtle.How do you actually prove
X
?X
is a conditional proposition, so you can start by assuming its premise to show its conclusion. This logical step corresponds to inserting a lambda. (Constructively, a proof of an implication is a mapping from proofs of the premise to proofs of the conclusion.)But now we have an assumption
x' :: X
, we can unfold the definition ofX
again to getf :: X -> Void
. In informal descriptions of Curry's paradox, there is no explicit "unfolding step", but in Haskell it corresponds to pattern-matching on the newtype constructor whenX
is an assumption, or applying the constructor whenX
is the goal (in fact, as we did above):Finally, we now have
f :: X -> Void
andx' :: X
, so we can deduceVoid
by function application: