我不明白为什么这个代码类型检查:
error1 :: ErrorT String (ReaderT Int IO) Int
error1 = asks id
仅供引用,
asks
有这种类型:asks :: Monad m => (r -> a) -> ReaderT r m a
另一方面,我能够理解,此代码类型检查:
reader1 :: ReaderT Int IO Int
reader1 = asks id
id
有类型 a -> a
并且有一个 Monad
的实例对于 IO
,因此编译器可以推断类型。这对我来说很清楚。ErrorT
是新类型和 haskell spec状态,(在关于新类型的部分):... it creates a distinct type that must be explicitly coerced to or from the original type ...
根据我的解释,我应该可以得到与
error1
中相同的类型。 仅限 明确地,有一些类似于这样的强制:reader2 :: ReaderT Int IO (Either String Int)
reader2 = fmap (\i -> Right i) reader1
error2 :: ErrorT String (ReaderT Int IO) Int
error2 = ErrorT reader2
但是,显然,自从
error1
排版检查就好了,我隐藏了一些知识。你能帮我揭开它吗?运行示例代码所需的导入:
import Control.Monad.Error (ErrorT(ErrorT))
import Control.Monad.Reader (ReaderT, asks)
最佳答案
函数asks
由两个类型略有不同的相关模块导出。来自 Control.Monad.Trans.Reader
的版本(transformers
包的一部分),具有问题中给出的类型:
asks :: Monad m => (r -> a) -> ReaderT r m a
但是,使用的版本似乎是
mtl
中的版本。包,来自 Control.Monad.Reader
模块,它具有以下更通用的类型:asks :: MonadReader r m => (r -> a) -> m a
所以示例定义
error1 :: ErrorT String (ReaderT Int IO) Int
error1 = asks id
意思是
MonadReader Int (ErrorT String (ReaderT Int IO))
必须持有。
也由
mtl
定义以下是 MonadReader
的实例:instance Monad m => MonadReader r (ReaderT r m)
instance (Error e, MonadReader r m) => MonadReader r (ErrorT e m)
有了这些,上面的约束减少到
(Error String, Monad IO)
两者都成立。
关于haskell - 隐式类型强制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26803583/