Lif*_*ang 8 monads haskell type-systems ghc
我只是设法了解了班级的定义 MonadReader
class Monad m => MonadReader r m | m -> r where
...
Run Code Online (Sandbox Code Playgroud)
在阅读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
Run Code Online (Sandbox Code Playgroud)
为了使上述编译,我们需要写
action :: ReadertT Int IO ()
action = do
x <- ask :: ReadertT Int IO Int
liftIO $ print x
Run Code Online (Sandbox Code Playgroud)
这是因为,如果没有 fundep,编译器就无法推断出它x是一个Int. 毕竟一个 monadReadertT 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.
Run Code Online (Sandbox Code Playgroud)
所以程序员必须提供一些强制的注释x :: Int,否则代码是不明确的。