mzero如何匹配守卫类型签名?

How does mzero match guard type signature?

我无法理解 guard 的工作原理。为什么要进行类型检查?是不是 mzero 能够返回一些 m a where a /= ()?

guard           :: (MonadPlus m) => Bool -> m ()
guard True      =  return ()
guard False     =  mzero

mzero :: m a 

是的,mzero 能够返回一些 m a,其中 a /= ()。但它也能够返回 m ()guard 在第二种情况下使用它。

类似这样:

n :: Int
n = 5

5 可以是 FloatDouble,但也可以是 Int。编译器在类型检查期间选择 5 所需的解释。

类似地,编译器在类型检查期间为原始示例中的 mzero 选择了正确的类型。更准确地说,它看到需要 m (),所以它选择了那个类型。

这里重要的一点是

mzero :: MonadPlus m => m a

其实就是

mzero :: forall m a . MonadPlus m => m a

表示 mzerocaller 可以选择 ma 的实际值(只要 m 是一个 MonadPlus)。因此,调用者可以选择 a=() 来进行类型检查。这个选择可以由用户通过类型注释做出,否则编译器将在类型检查期间尝试推断正确的选择。