module Problem2.Proof where
import Problem2.Prod
-- I present the proof "in Haskell" just to be able to check the types
-- of the steps - this is not required.
type EqProof = []
-- Poor man's equality proofs - a list of (supposedly) equal
-- expression "proving" the equality of the first and the last
-- expression by a series of motivated steps
----------------
proof_LeftId :: (Monad m, Monad n) => a -> (a -> Prod m n b) -> EqProof (Prod m n b)
proof_LeftId a f =
[ return a >>= (\x -> f x)
, -- def. of return
Prod (return a, return a) >>= (\x -> f x)
, -- def. of (>>=)
Prod ( return a >>= (fstP . f)
, return a >>= (sndP . f) )
, -- LeftId law for m and for n
Prod ( (fstP . f) a
, (sndP . f) a )
, -- def. of composition
Prod ( fstP (f a)
, sndP (f a) )
, -- SurjectivePairing
Prod ( unProd (f a) )
, -- Inverses
f a
]
----------------
proof_RightId :: (Monad m, Monad n) => Prod m n a -> EqProof (Prod m n a)
proof_RightId mx =
[ mx >>= return
, -- inverses
Prod (unProd mx) >>= return
, -- surjectivePairing
Prod (fstP mx, sndP mx) >>= return
, -- def. of (>>=), return
{- -- commented out due to ambiguous type variables
Prod ( fstP mx >>= (fstP . returnProd)
, sndP mx >>= (sndP . returnProd) )
, -- fstP_return and sndP_return
-}
Prod ( fstP mx >>= return
, sndP mx >>= return )
, -- RightId law for m and for n
Prod ( fstP mx
, sndP mx )
, -- surjectivePairing
Prod (unProd mx)
, -- Inverses
mx
]
{-
-- commented out due to ambiguous type variables
fstP_return x =
[ (fstP . returnProd) x
, -- def. of (.)
fst (unProd (returnProd x))
, -- def. of returnProd
fst (unProd (Prod (return x, return x)))
, -- Inverses
fst (return x, return x)
, -- def. of fst
return x
]
sndP_return :: (Monad n) => a -> n a
sndP_return x =
[ (sndP . returnProd) x
, -- as in fstP_return
return x
]
-}
-- ----------------------------------------------------------------
proof_Assoc :: (Monad m, Monad n) => Prod m n c -> (c -> Prod m n b) -> (b -> Prod m n a) -> EqProof (Prod m n a)
proof_Assoc mx f g =
[ (mx >>= f) >>= g
, -- Inverses, surjectivePairing
(Prod (fstP mx, sndP mx) >>= f) >>= g
, -- Def. of (>>=)
(Prod ( fstP mx >>= (fstP . f)
, sndP mx >>= (sndP . f) ) ) >>= g
, -- Def. of (>>=)
Prod ( (fstP mx >>= (fstP . f)) >>= (fstP . g)
, (sndP mx >>= (sndP . f)) >>= (sndP . g))
, -- Assoc. law for the underlying monads m and n
Prod ( fstP mx >>= \x -> (fstP . f) x >>= (fstP . g)
, sndP mx >>= \y -> (sndP . f) y >>= (sndP . g) )
, -- Def. of (.)
Prod ( fstP mx >>= \x -> fstP (f x) >>= (fstP . g)
, sndP mx >>= \y -> sndP (f y) >>= (sndP . g) )
, -- fstP_distributes and sndP_distributes
Prod ( fstP mx >>= \x -> fstP (f x >>= g)
, sndP mx >>= \y -> sndP (f y >>= g) )
, -- Def. of (.) + alpha renaming
Prod ( fstP mx >>= (fstP . (\x -> f x >>= g))
, sndP mx >>= (sndP . (\x -> f x >>= g)) )
, -- def. of (>>=)
Prod (fstP mx, sndP mx) >>= (\x -> f x >>= g)
, -- def. of return
Prod (fstP mx, sndP mx) >>= (\x -> f x >>= g)
, -- expand mx
mx >>= (\x -> f x >>= g)
]
----------------------------------------------------------------
-- Not part of the exam question
fstP_distributes :: (Monad m, Monad n) =>
(c -> Prod m n b) -> (b -> Prod m n a) -> c -> EqProof (m a)
fstP_distributes f g x =
[ fstP (f x) >>= (fstP . g)
, -- Def. of fstP
fst (unProd (f x)) >>= (fstP . g)
, -- Def. of fst
fst ( fst (unProd (f x)) >>= (fstP . g)
, snd (unProd (f x)) >>= (sndP . g) )
, -- Inverses
fst (unProd (Prod ( fst (unProd (f x)) >>= (fstP . g)
, snd (unProd (f x)) >>= (sndP . g) )))
, -- def. of (>>=), fstP
fstP (Prod (fst (unProd (f x)), snd (unProd (f x))) >>= g)
, -- expand (f x)
fstP (f x >>= g)
]
-- sndP_distributes is similar
----------------------------------------------------------------
-- Just some type checking of the laws
prop_LeftId :: (Monad m) => (m a -> m a -> t) -> b -> (b -> m a) -> t
prop_RightId :: (Monad m) => (m a -> m a -> t) -> m a -> t
prop_Assoc :: (Monad m) => (m a -> m a -> t) -> m c -> (c -> m b) -> (b -> m a) -> t
prop_LeftId (~=) a f = ( return a >>= (\x -> f x)) ~= ( f a )
prop_RightId (~=) mx = ( mx >>= (\x -> return x) ) ~= ( mx )
prop_Assoc (~=) mx f g = ( (mx >>= f) >>= g ) ~= ( mx >>= (\x -> f x >>= g) )