看看这个例子:
ReaderT Integer (ErrorT String (StateT Integer Identity)) Integer
Run Code Online (Sandbox Code Playgroud)
(>>=)这里将使用什么操作符绑定?
例如,如果我们使用do表示法,那么编译器会选择哪个绑定运算符?
供参考,(>>=)有类型
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)
并注意到
ReaderT Integer (ErrorT String (StateT Integer Identity)) Integer
Run Code Online (Sandbox Code Playgroud)
是相同的
(ReaderT Integer (ErrorT String (StateT Integer Identity))) Integer
Run Code Online (Sandbox Code Playgroud)
因为类型应用程序(如函数应用程序)在Haskell中是左关联的.
所以,给定
x :: ReaderT Integer (ErrorT String (StateT Integer Identity)) Integer
Run Code Online (Sandbox Code Playgroud)
和f表达式中的适当类型
x >>= f
Run Code Online (Sandbox Code Playgroud)
类型检查器将尝试匹配x左参数类型的类型(>>=).这意味着它会试图统一ReaderT Integer (ErrorT String (StateT Integer Identity)) Integer使用m a.这个统一的唯一途径是采取a以Integer和m为ReaderT Integer (ErrorT String (StateT Integer Identity)).因此,使用~类型相等表示法,我们最终得到
m ~ (ReaderT Integer (ErrorT String (StateT Integer Identity)))
a ~ Integer
Run Code Online (Sandbox Code Playgroud)
因此,它必须使用,where 和的(ReaderT r n)实例.Monadr ~ Integern ~ ErrorT String (StateT Integer Identity)
这是类型统一在Haskell中的工作原理的结果,而不仅仅是for (>>=),因此这个一般的想法可以用于解释其他多态函数的类型检查是如何工作的.