有一个针对读取器monad的ask函数,它完全定义为读取器函数,为什么它作为一个单独的函数存在,其定义与阅读器相同? 为什么不总是使用阅读器?
class Monad m => MonadReader r m | m -> r where
-- | Retrieves the monad environment.
ask :: m r
ask = reader id
-- | Executes a computation in a modified environment.
local :: (r -> r) -- ^ The function to modify the environment.
-> m a -- ^ @Reader@ to run in the modified environment.
-> m a
-- | Retrieves a function of the current environment.
reader :: (r -> a) -- ^ The selector function to apply to the environment.
-> m a
reader f = do
r <- ask
return (f r)
-- | Retrieves a function of the current environment.
asks :: MonadReader r m
=> (r -> a) -- ^ The selector function to apply to the environment.
-> m a
asks = reader
我找到了将这种冗余引入变压器包和 mtl 包的补丁。补丁/提交说明是...不是超级有启发性。然而,在这两种情况下,asks
早于reader
,并且在这两种情况下,相同的更改引入了state
和writer
原语。
所以,一些猜测:
- 据观察,将转换器/monad 类的核心语义作为库中表示的概念很方便。
- 为了可预测性,新的原语以提供该原语而没有其他任何东西的变压器命名(
StateT
->state
;WriterT
->writer
;ReaderT
->reader
)。这种并行性使用户更容易记住他们想要的东西叫什么。 - 由于
asks
已经存在,因此保留了它以保持一点向后兼容性。
如果我们想要一个明确的答案,我们可能不得不问Ed Kmett或Twan van Laarhoven,他们是这些变化的明显发起者。