Tratemos de demostrar los siguientes teoremas construyendo programas que compilen.

Ejercicio 1: Identidad “Dado que asumimos A, concluimos A”.

identidad :: a -> a
identidad a = a

Ejercicio 2: Constante**

constante :: a -> b -> a
constante a b = a

Ejercicio 3: Modus Ponens

modusPonens :: (a -> b) -> a -> b
modusPonens f x = f x

Ejercicio 4: Silogismo Hipotético

transitividad :: (a -> b) -> (b -> c) -> (a -> c)
transitividad f g x = g (f x)
-- También válido usando composición:
-- transitividad f g = g . f

Ejercicio 5: Conmutatividad de la Conjunción ****

conjConmuta :: (a, b) -> (b, a)
conjConmuta (x, y) = (y, x)

Ejercicio 6: El problema de la Negación y Lógica Intuicionista En Haskell, el tipo Void (que no tiene constructores) representa lo falso ().

data Falso -- Tipo sin constructores
type Not a = a -> Falso
 
{-# LANGUAGE EmptyCase #-}
exFalso :: Falso -> a
exFalso x = case x of {}

¿Qué pasa con el Tercio Excluso () o la Doble Negación?

-- dobleNeg :: Not (Not a) -> a
-- dobleNeg = ???
 
-- tercioExcluso :: Either a (Not a)
-- tercioExcluso = ???

Nos quedaremos atrapados. ¿Por qué? Porque lenguajes como Haskell (y asesores de pruebas como Rocq o LEAN) operan bajo lógica constructivista. Si afirmas que algo existe o es verdadero, tienes que construir el algoritmo para obtenerlo.

Resumen

ProposiciónTipo
Implicación a -> b
Conjunción (a, b)
Disyunción Either a b
Verdadero ()()
Falso ()Void
Negación a -> Void
Reglas en Deducción NaturalOperaciones en Haskell
Intro \x -> ...
Elim f x
Intro (x, y)
Elim fst p, snd p
Intro Left x, Right y
Elim case x of {Left a -> ...; Right b -> ...}