Tratemos de demostrar los siguientes teoremas construyendo programas que compilen.
Ejercicio 1: Identidad “Dado que asumimos A, concluimos A”.
identidad :: a -> a
identidad a = aEjercicio 2: Constante**
constante :: a -> b -> a
constante a b = aEjercicio 3: Modus Ponens
modusPonens :: (a -> b) -> a -> b
modusPonens f x = f xEjercicio 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 . fEjercicio 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ón | Tipo |
|---|---|
| Implicación | a -> b |
| Conjunción | (a, b) |
| Disyunción | Either a b |
| Verdadero () | () |
| Falso () | Void |
| Negación | a -> Void |
| Reglas en Deducción Natural | Operaciones 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 -> ...} |