I implemented three of the four De Morgan's Laws in Haskell:
notAandNotB :: (a -> c, b -> c) -> Either a b -> c
notAandNotB (f, g) (Left x) = f x
notAandNotB (f, g) (Right y) = g y
notAorB :: (Either a b -> c) -> (a -> c, b -> c)
notAorB f = (f . Left, f . Right)
notAorNotB :: Either (a -> c) (b -> c) -> (a, b) -> c
notAorNotB (Left f) (x, y) = f x
notAorNotB (Right g) (x, y) = g y
However, I don't suppose that it's possible to implement the last law (which has two inhabitants):
notAandBLeft :: ((a, b) -> c) -> Either (a -> c) (b -> c)
notAandBLeft f = Left (\a -> f (a, ?))
notAandBRight :: ((a, b) -> c) -> Either (a -> c) (b -> c)
notAandBRight f = Right (\b -> f (?, b))
The way I see it, there are two possible solutions:
- Use
undefined
in place of?
. This is not a good solution because it's cheating. Either use monomorphic types or bounded polymorphic types to encode a default value.
notAandBLeft :: Monoid b => ((a, b) -> c) -> Either (a -> c) (b -> c) notAandBLeft f = Left (\a -> f (a, mempty)) notAandBRight :: Monoid a => ((a, b) -> c) -> Either (a -> c) (b -> c) notAandBRight f = Right (\b -> f (mempty, b))
This is not a good solution because it's a weaker law than De Morgan's law.
We know that De Morgan's laws are correct but am I correct in assuming that the last law can't be encoded in Haskell? What does this say about the Curry-Howard Isomorphism? It's not really an isomorphism if every proof can't be converted into an equivalent computer program, right?