【问题标题】:Type class constraint with multiple variables具有多个变量的类型类约束
【发布时间】:2016-02-18 02:06:26
【问题描述】:

我很难掌握 Monad Reader 函数的以下类型类约束,它接收多个变量,

local :: MonadReader r m => (r -> r) -> m a -> m a  

如何正确理解类型类约束?哪个是类型构造函数,rm 或两者兼而有之? (从m a 部分它建议类型构造函数是m)。

与例如绑定函数相比,类型类约束只允许单个参数;

(>>=) :: Monad m => m a -> (a -> m b) -> m b 

与上面的本地函数不同,很明显并且很容易理解绑定函数的类型类约束要求类型构造函数m 是一个Monad 实例。

【问题讨论】:

标签: haskell typeclass


【解决方案1】:

在这些情况下,最好在此处查看课程 (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(基本上什么都没有 - 它没有效果)


(我希望可以复制和粘贴它...如果不是请告诉我或删除它)

【讨论】:

  • 它是在 BSD 风格的许可证下,所以复制和粘贴归属地应该是安全的。
  • 首先感谢@Carsten 的回答。我难以理解本地函数的类型,从类型类约束中流出。对于 bind 函数,我可以很容易地看到 m 必须是 Monad 实例,而对于本地函数,起初我认为 r m 的乘积必须是 Monad 实例。这会令人困惑,因为显然r 的类型是*,而m 的类型是* -&gt; *。这是否意味着声明类型类约束不能作为函数操作?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-21
  • 1970-01-01
  • 2015-04-26
  • 2019-09-23
  • 1970-01-01
  • 2018-03-05
  • 1970-01-01
相关资源
最近更新 更多