Curry's paradox in Haskell?
Asked Answered
W

1

6

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?
Wallace answered 12/10, 2019 at 8:18 Comment(2)
You can't construct a term of type Void without using fix or some kind recursion (either at the term level or at the type level). If you remove all the ways to recurse forever or cause runtime errors (like undefined), then the language becomes normalizing, so every t :: T reduces to some t' :: T which is a normal form, "starting" with a constructor of T (or a lambda if that's a function type). Void has no constructors, so that's impossible.Slaby
@Slaby If you could repeat that as an answer to a question nearby.Wallace
A
4

The encoding of Curry's paradox looks more like this:

x :: X
x = X (\x'@(X f) -> f x')

X can indeed be read as the sentence "if X is true, then there is a contradiction", or equivalently, "X is false".

But using fix to prove X is not really meaningful, because fix is blatantly incorrect as a reasoning principle. Curry's paradox is more subtle.

How do you actually prove X?

x :: X
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.)

x :: X
x = X (\x' -> _)

But now we have an assumption x' :: X, we can unfold the definition of X again to get f :: 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 when X is an assumption, or applying the constructor when X is the goal (in fact, as we did above):

x :: X
x = X (\x'@(X f) -> _)

Finally, we now have f :: X -> Void and x' :: X, so we can deduce Void by function application:

x :: X
x = X (\x'@(X f) -> f x')
Albano answered 12/10, 2019 at 13:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.