I'm trying to complete the monadLeftIdentity proof for the following data type:
data ErrorM : (a : Type) -> Type where
AllGood : a -> ErrorM a
Error : String -> ErrorM a
instance Monad ErrorM where
(AllGood x) >>= f = f x
(Error err) >>= f = Error err
instance VerifiedMonad ErrorM where
monadApplicative (AllGood f) (AllGood x) = Refl
monadApplicative (Error err) (AllGood x) = Refl
monadApplicative (AllGood f) (Error err) = Refl
monadApplicative (Error er1) (Error er2) = Refl
monadLeftIdentity x f = ?z
I've left out the instances for Functor, Applicative and their Verified counterparts, as they're quite verbose and trivial. Do let me know, can paste them all here.
I've tried to rewrite return x as pure x or AllGood x, but have been unsuccessful in doing so (the rewrite does nothing to the proof state).
I've also tried to refine return x like so:
monadLeftIdentity x f with (return x)
monadLeftIdentity x' f | AllGood x' = ?z
but I get the following err msg:
`-- Error.idr line 51 col 22:
When elaborating left hand side of with block in Prelude.Monad.Astra.Error.ErrorM instance of Prelude.Monad.VerifiedMonad, method monadLeftIdentity:
Can't match on with block in Prelude.Monad.Astra.Error.ErrorM instance of Prelude.Monad.VerifiedMonad, method monadLeftIdentity a (AllGood x') x' b f return
How does one go about this?
This seems like a bug in the Idris typechecker that doesn't resolve overloaded functions even when they are completely determined by the type.
To witness, I can make a proof like this:
myLeftIdentity : (x : a) -> (f : a -> ErrorM b) -> return x >>= f = f x
myLeftIdentity x f = Refl
and it typechecks just fine, but it can't be used as a witness in the instance:
instance VerifiedMonad ErrorM where
monadApplicative (AllGood _) (AllGood _) = Refl
monadApplicative (Error _) _ = Refl
monadApplicative (AllGood _) (Error _) = Refl
monadLeftIdentity = myLeftIdentity
results in
Can't unify
(x : a) -> (f : a -> ErrorM b) -> return x >>= f = f x
with
(x : a) -> (f : a -> ErrorM b) -> Main.ErrorM instance of Prelude.Monad.Monad, method >>= (return x) f = f x
even though the two >>= should be one and the same.
Interestingly, I was able to work around this by defining my own version of the Monad and VerifiedMonad classes:
infixl 5 >>=>
class Applicative m => Monad' (m : Type -> Type) where
(>>=>) : m a -> (a -> m b) -> m b
return' : Monad' m => a -> m a
return' = pure
instance Monad' ErrorM where
(AllGood x) >>=> f = f x
(Error err) >>=> f = Error err
class (Monad' m, VerifiedApplicative m) => VerifiedMonad' (m : Type -> Type) where
monadLeftIdentity : (x : a) -> (f : a -> m b) -> return' x >>=> f = f x
instance VerifiedMonad' ErrorM where
monadLeftIdentity x f = Refl
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With