Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 读卡器monad核心运算符不工作_Haskell - Fatal编程技术网

Haskell 读卡器monad核心运算符不工作

Haskell 读卡器monad核心运算符不工作,haskell,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

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

失败,已加载模块:无。

正确的实现是:

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
。由于此参数不存在,因此它声称在构建读卡器时,您将
r->a
误认为
a
(换句话说,当它只需要
r->a
时,您将
r->r->a
交给了它)

要查看发生了什么,检查runReader的类型可能会有所帮助:

ghci> :t runReader
runReader :: Reader r a -> r -> a
此函数将读取器作为其第一个参数,将读取器作为其第二个参数,并返回一个
a
。因此,我们可以看到子表达式

\r -> runReader (f $ m r) r
具有类型
r->a
,是将其交给
读取器
构造函数的好人选。如果您取消最后一个
r
,您只对一个参数应用了
runReader
,结果得到了当前的
r->a
函数,因此:

\r -> runReader (f $ m r)

具有类型
r->r2->a
,当您将其提供给读卡器时,您将获得
读卡器r(r2->a)
,但它的类型不适合
>=

请参阅后面的编辑我想在进行模式匹配时可能需要括号
(Reader m)
。正确答案是(runReader(f a))r我在前面的评论中看到过,我只是想知道它是否正确,为什么是这样。给谁先贴的:把它作为答案。我还收到了这样一条警告:“Reader”是Monad的一个实例,但不适用于应用程序-这将成为GHC 7.10中的一个错误,根据应用程序Monad的建议。@genisage您可以解释这是正确的,因为您为
m
f(mr)
的结果提供了相同的
r
,这正是读卡器monad的设计目的。您希望它对所有内容都使用完全相同的
r
,而
>=
的这个定义意味着它必须保持不变。@CosminMihai关于不作为Applicationve实例的警告对于玩游戏来说并不太重要,但是如果您想让您的自定义阅读器monad成为hackage上共享的东西,您需要确保应用程序实例存在。这也意味着您将需要一个函子实例,但这两个实例在谷歌搜索后都非常简单。