【发布时间】:2014-12-10 20:33:19
【问题描述】:
我正在尝试制作 Reader monad,但它不起作用(加载),我做错了什么?谢谢
newtype Reader r a = Reader { runReader :: r -> a }
instance Monad (Reader r) where
return a = Reader $ \r -> a
Reader m >>= f = Reader $ \r ->
let a = m r
in runReader (f a)
我收到此错误:
Couldn't match type ‘b’ with ‘r -> b’
‘b’ is a rigid type variable bound by
the type signature for
(>>=) :: Reader r a -> (a -> Reader r b) -> Reader r b
at Reader.hs:24:14
Expected type: Reader r b
Actual type: Reader r (r -> b)
Relevant bindings include
f :: a -> Reader r b (bound at Reader.hs:24:18)
m :: r -> a (bound at Reader.hs:24:12)
(>>=) :: Reader r a -> (a -> Reader r b) -> Reader r b
(bound at Reader.hs:24:5)
In the expression: Reader $ \ r -> let a = ... in runReader (f a)
In an equation for ‘>>=’:
(Reader m) >>= f = Reader $ \ r -> let ... in runReader (f a)
In the instance declaration for ‘Monad (Reader r)’
失败,已加载模块:无。
【问题讨论】:
-
请看后面的编辑
-
我认为您在进行模式匹配时可能需要括号
(Reader m) -
正确答案是 (runReader (f a)) r 我之前在评论中看到过,我只是想知道它是否正确,为什么会这样。给谁先贴:把它作为答案。我也收到此警告“Reader”是 Monad 的一个实例,但不是 Applicative - 根据 Applicative-Monad 提案,这将成为 GHC 7.10 中的错误。
-
@genisage 您可以解释这是正确的,因为您为
m和f (m r)的结果提供了相同的r,这正是阅读器monad 的设计目的。您希望它对所有内容都使用完全相同的r,而>>=的这个定义意味着必须保持。 -
@CosminMihai 关于不是 Applicative 实例的警告对于玩弄并不是太重要,但是如果您要将自定义阅读器 monad 变成在 hackage 上分享的东西,您需要确保应用实例存在。这也意味着您需要一个仿函数实例,但经过一番谷歌搜索后,这两个实例都非常简单。
标签: haskell