我很难掌握Monad Reader函数的以下类型类约束,它接收多个变量,
id
如何正确理解类型类约束?哪一个是类型构造函数,local :: MonadReader r m => (r -> r) -> m a -> m a
或r
或两者? (来自m
部分,它建议类型构造函数为m a
)。
与例如绑定函数相比,其中类型类约束仅允许单个参数;
m
与上面的本地函数不同,很明显且很容易理解bind函数的类型类约束需要类型构造函数(>>=) :: Monad m => m a -> (a -> m b) -> m b
作为Monad实例。
答案 0 :(得分:2)
在这些情况下,最好在这里查看课程(MonadReader)。
你会发现这个:
class Monad m => MonadReader r m | m -> r where
还有更多。
所以这里m
是一些monad,r
将是你读的东西(MonadReader
是一个所谓的monad-transformer ...好吧不太好 - 这是班级这对所有变形金刚来说都很常见 - ReaderT
是变形金刚......但解释真的太可怕了......对不起)
local
用于更改您读取的内容(我喜欢将其视为配置或环境) - r->r
部分 - 给您一个monad m
中的计算将进行此更改。
如果你在文档中阅读,甚至有一个如何使用它的例子:
calculateContentLen :: Reader String Int
calculateContentLen = do
content <- ask
return (length content);
-- Calls calculateContentLen after adding a prefix to the Reader content.
calculateModifiedContentLen :: Reader String Int
calculateModifiedContentLen = local ("Prefix " ++) calculateContentLen
main = do
let s = "12345";
let modifiedLen = runReader calculateModifiedContentLen s
let len = runReader calculateContentLen s
putStrLn $ "Modified 's' length: " ++ (show modifiedLen)
putStrLn $ "Original 's' length: " ++ (show len)
正如您所看到的,local
用于在字符串前面添加"Prefix "
请注意,此示例中的monad m
不 IO
- 它是Identity
(基本上没有 - 它有没有效果)
(我希望可以复制并粘贴它......如果没有,请告诉我或删除它)