已验证错误monad的单个实例

时间:2015-02-12 04:44:10

标签: idris

我正在尝试完成以下数据类型的monadLeftIdentity证明:

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

我遗漏了FunctorApplicative及其Verified对应的实例,因为它们非常冗长和琐碎。请告诉我,可以将它们全部粘贴在这里。

我尝试将return x重写为pure xAllGood x,但这样做并不成功(重写对证明状态没有任何作用)。

我也试图像这样改进return x

  monadLeftIdentity x f with (return x)
    monadLeftIdentity x' f | AllGood x' = ?z

但我得到以下错误信息:

 `-- 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

如何解决这个问题?

1 个答案:

答案 0 :(得分:3)

这似乎是Idris类型检查器中的一个错误,即使它们完全由类型决定,它也无法解决重载函数。

见证,我可以做出这样的证明:

myLeftIdentity : (x : a) -> (f : a -> ErrorM b) -> return x >>= f = f x
myLeftIdentity x f = Refl

它的类型很好,但它不能在实例中用作证人:

instance VerifiedMonad ErrorM where
  monadApplicative (AllGood _) (AllGood _) = Refl
  monadApplicative (Error _) _ = Refl
  monadApplicative (AllGood _) (Error _) = Refl

  monadLeftIdentity = myLeftIdentity

结果

 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

即使两个>>=应该是同一个。

有趣的是,通过定义我自己的MonadVerifiedMonad类版本,我能够解决这个问题:

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