blog

Type Algebra: 2+2 = 2*2

“Since 2*2 == 2+2, then (Boolean, Boolean) is equivalent to Boolean | Boolean” – Tony Morris

Word.

Below is how you can construct these two types in Haskell, and show their equivalence. It’s interesting the different ways each type encodes the same data. One encodes the two booleans as the first and second member of the pair, whereas the other encodes one boolean as “which constructor did you pick” and the other as “what boolean did you pass to the constructor”. I think the names of the two constructors (“TrueAnd” and “FalseAnd”) highlight how the encoding works.

module BoolEquivalent where

import Test.QuickCheck

data B2 = TrueAnd Bool | FalseAnd Bool
 deriving (Eq, Show)

data P2 = P2 (Bool, Bool)
 deriving (Eq, Show)

pToB :: P2 -> B2
pToB (P2 (True, x)) = TrueAnd x
pToB (P2 (False, x)) = FalseAnd x

bToP :: B2 -> P2
bToP (TrueAnd x) = P2 (True, x)
bToP (FalseAnd x) = P2 (False, x)

instance Arbitrary B2 where
 arbitrary = oneof $ return `fmap` [TrueAnd True, TrueAnd False, FalseAnd True, FalseAnd False]

instance Arbitrary P2 where
 arbitrary = oneof $ (return . P2) `fmap` [(True, True), (True, False), (False, True), (False, False)]

prop_inverse1 :: B2 -> Bool
prop_inverse1 x = (pToB . bToP) x == x

prop_inverse2 :: P2 -> Bool
prop_inverse2 x = (bToP . pToB) x == x

go = do
 quickCheck prop_inverse1
 quickCheck prop_inverse2

Leave a Reply

*