我只是设法了解了MonadReader
类的定义
class Monad m => MonadReader r m | m -> r where
...
在阅读Haskell中的功能依赖文档之后,现在我可以理解
| m -> r
指定类型变量r
由m
唯一地确定。基于到目前为止我所见过的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
这是因为,在没有资助者的情况下,编译器无法推断
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
的注释,否则代码将变得模棱两可。