你可以通过执行一些替换来说服自己它是有效的。首先看签名
createUser
Reader
:
createUser :: Reader Permissions (Maybe User)
{- definition of Reader -}
createUser :: ReaderT Permissions Identity (Maybe User)
ReaderT
类型只有一个数据构造函数:
ReaderT (r -> m a)
,这意味着
是一个计算为类型值的项
ReaderT (Permissions -> Identity (Maybe User))
. 如您所见,它只是一个带有
. 它不必凭空创建任何内容,但将接收类型的值
Permissions
do
符号只是句法上的糖,表达式:
do permissions <- ask
if hasPermission "admin" permissions
then map Just newUser
else pure Nothing
ask >>= \permissions ->
if hasPermission "admin" permissions
then map Just newUser
else pure Nothing
ask
,
>>=
pure
对于
ReaderT公司
ask >>= \permissions -> ...
{- definition of ask for ReaderT -}
ReaderT pure >>= \permissions -> ...
{- definition of >>= for ReaderT -}
ReaderT \r ->
pure r >>= \a -> case (\permissions -> ...) a of ReaderT f -> f r
{- function application -}
ReaderT \r ->
pure r >>= \a ->
case (if hasPermission "admin" a
then map Just newUser
else pure Nothing) of ReaderT f -> f r
{- definition of pure for Identity -}
ReaderT \r ->
Identity r >>= \a ->
case (if hasPermission "admin" a
then map Just newUser
else pure Nothing) of ReaderT f -> f r
{- definition of >>= for Identity -}
ReaderT \r ->
(\a ->
case (if hasPermission "admin" a
then map Just newUser
else pure Nothing) of ReaderT f -> f r) r
{- function application -}
ReaderT \r ->
case (if hasPermission "admin" r
then map Just newUser
else pure Nothing) of ReaderT f -> f r
正如你所见,
创建用户
显然只是一个由
在表达式中穿插一个值(“环境”)。
runReader
展开函数并使用提供的参数调用它:
runReader :: forall r a. Reader r a -> r -> a
runReader (ReaderT f) r = f r