haskell - 隐式类型强制?

标签 haskell monad-transformers newtype

我不明白为什么这个代码类型检查:

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/

相关文章:

haskell - 为什么 ghc 8.8.4 无法编译 ghci 可以加载的文件?

haskell - 在像 exceptT a IO 这样的 monad 堆栈中管理资源的最佳方法是什么?

scala - 猫从 monad 堆栈中获取值(value)

scala - 使用相同谓词进行细化时,如何使用 Scala 的 Refined 库确保类型安全

haskell - F# 有 Haskell 的 'newtype' 吗?

haskell - (\f -> fmap f id) 是否总是等价于 arr?

haskell - 强制严格评估——我做错了什么?

haskell - 如何使免费的 monad 解释器递归?

c# - C#'s equivalent to Haskell' 的新类型是什么?

haskell - 我的第一个 Haskell 程序有哪些可以改进的地方?