haskell - 为什么定义 MonadReader 需要 FunctionalDependency?

标签 haskell monads ghc type-systems

我只是设法理解了类的定义MonadReader

class Monad m => MonadReader r m | m -> r where
...

看了Haskell中的Functional Dependency的文档,现在可以理解为| m -> r指定类型变量 rm 唯一决定.根据我目前看到的几个 MonadReader 的典型实例(例如 Reader ),我认为这个要求是合理的,但在我看来,我们仍然可以定义像 Reader 这样的实例。即使没有这个函数依赖子句。

我的问题是为什么我们在 MonadReader 的定义中需要函数依赖?从某种意义上说,这对于定义 MonadReader 是否在功能上是必要的,没有它就无法正确定义 MonadReader,或者它只是限制 MonadReader 的使用方式,以便 MonadReader 的实例都以某种预期的方式运行?

最佳答案

需要以对用户更方便的方式进行类型推断。

例如,如果没有fundep,这将无法编译:

action :: ReaderT Int IO ()
action = do
  x <- ask
  liftIO $ print x

要进行上述编译,我们需要编写
action :: ReadertT Int IO ()
action = do
  x <- ask :: ReadertT Int IO Int
  liftIO $ print x

这是因为,没有fundep,编译器无法推断x。是 Int .毕竟是一个单子(monad)ReadertT Int IO可能有多个实例
instance MonadReader Int (ReaderT Int IO) where
   ask = ReaderT (\i -> return i)
instance MonadReader Bool (ReaderT Int IO) where
   ask = ReaderT (\i -> return (i != 0))
instance MonadReader String (ReaderT Int IO) where
   ask = ReaderT (\i -> return (show i))
-- etc.

所以程序员必须提供一些注释来强制 x :: Int ,或者代码不明确。

关于haskell - 为什么定义 MonadReader 需要 FunctionalDependency?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58947160/

相关文章:

haskell - 伴随仿函数决定了单子(monad)更改器(mutator),但是升力在哪里呢?

haskell - PolyKinds 的不明确类型

haskell - 是否可以在没有 prof 库的情况下分析 Haskell 程序?

haskell - 如何从 Haskell 中的文件中逐行读取

haskell - 在Haskell中创建任意嵌套的列表结构

javascript - 在函数式编程中,为什么IO的join方法要运行unsafePerformIO两次?

scala - 如果值不为空,则添加到列表

Haskell 默认父类(super class)实例

haskell - 不寻常的种类和数据构造函数

Haskell 堆栈与全局 ghc