读者monad核心运营商不工作

时间:2014-12-10 20:33:19

标签: haskell

我正在尝试制作一个阅读器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)’

失败,模块加载:无。

1 个答案:

答案 0 :(得分:2)

正确的实施是:

newtype Reader r a = Reader { runReader :: r -> a }

instance Monad (Reader r) where
    return a = Reader $ \_ -> a
    Reader m >>= f = Reader $ \r -> runReader (f $ m r) r

您缺少的额外混淆是绑定中的最终r。由于此参数不存在,因此它声称您在构建Reader时误将r -> a误认为a(换句话说,您在需要时将r -> r -> a传递给r -> a只是ghci> :t runReader runReader :: Reader r a -> r -> a )。

要了解正在发生的事情,可能有助于检查runReader的类型:

r

此函数将读者的第一个参数作为其第二个参数a,并返回\r -> runReader (f $ m r) r 。因此我们可以看到子表达式

r -> a

具有类型Reader,是传递给r构造函数的好选择。如果你遗漏了最后runReader,你只将r -> a应用于一个参数,结果你得到了curry \r -> runReader (f $ m r) 函数,那么:

r -> r2 -> a

的类型为Reader r (r2 -> a),当您将其提供给阅读器时,您将获得>>=,{{1}}的类型不正确。