为什么可以替换这些类型?

1 monads haskell monad-transformers

有些事情似乎令人难以置信:

foo :: a -> StateT Env (ReaderT Env (ErrorT String IO)) String

可以替换为
foo :: a -> ErrorT String IO String

这怎么可能 ?毕竟,他们是完全不同的类型......

lef*_*out 7

显然,在所有情况下不可能相互替换它们.例如,如果你明确使用ErrorT . return $ Left "Muahar",那么这必须是一个ErrorT String m a.

然而,这两种类型的形式为a -> M String,具有(变压器堆栈)单子M这是一个实例MonadIOMonadError String.因此,如果仅使用表单的操作定义此函数liftIO ioaction,并且可能throwErrorcatchError,则它将作为任何这些monad工作.一般类型是

foo :: (MonadIO m, MonadError String m) => a -> m String
Run Code Online (Sandbox Code Playgroud)

  • 如果从`foo`中删除自己的类型签名然后在ghci中使用`:t foo`,你可以看到`foo`可以拥有的最常规类型,这通常非常有用.在找出monad堆栈时,`:someFunctionOrTypeOrTypeClass`也非常有用. (2认同)