Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.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,我正在学习这个教程 它的树函数让我很尴尬 tom :: Reader String String tom = do env <- ask return (env ++ " This is tom.") jerry :: Reader String String jerry = do env <- ask return (env ++ " This is Jerry.") tomAndJerry :: Reader Strin

我正在学习这个教程

它的树函数让我很尴尬

tom :: Reader String String
tom = do
  env <- ask
  return (env ++ " This is tom.")

jerry :: Reader String String
jerry = do
  env <- ask
  return (env ++ " This is Jerry.")

tomAndJerry :: Reader String String
tomAndJerry = do
   t <- tom
   j <- jerry
   return (t ++ "\n" ++ j)

runJerryRun :: String
runJerryRun  = (runReader tomAndJerry) "Who is this?"
tom::阅读器字符串
汤姆=做

env前两个函数都返回自己的读卡器monad实例。然后,您可以将它们组合在一起(在第三个函数中)

对于参数,让我们用
IO
替换
Reader
,并执行类似操作,这些函数都不接收任何参数:

getIntFromFile::IO Int
getIntFromFile=do

我认为丹尼尔·瓦格纳在评论中提到了一个重要的误解。
Reader
是(包装)一个函数,因此它接受参数。鉴于此,我猜你的最后一个问题

我的读者monad是一种全球性的吗

有一个答案:是的,从某种意义上说,读者monad提供了一种通过链式计算传递不可变状态/环境的方法;所以它每次调用时(通过
ask
)都会读取相同的值

在您的代码中,这意味着两个
ask
s(或者相当于
tom
jerry
)都读取相同的环境,由字符串
“这是谁?”
表示

嗯,通过去除
do
s:

tom::阅读器字符串
汤姆=询问>>=\env->返回(env++“我是汤姆”)
jerry::读卡器字符串
jerry=询问>>=\env->返回(env++“我是jerry”)
tomAndJerry::读取器字符串
tomAndJerry=tom>>=\t->jerry>=\j->return(t++“\n”+++j)
这里的
>=
需要一个返回单子的函数,但是你没有它,你有一个“普通”函数(例如
\env->env++“This is Tom.”
),所以你必须使用
return
将结果包装回单子。然后,而不是使用
>=
返回。f
,既然我们只需要在monad中应用一个函数,为什么不使用
fmap f

这意味着我们可以通过使用
tom
Functor
jerry
以及
tomAndJerry
Applicative
来进一步简化

tom::阅读器字符串
汤姆=fmap(++“我是汤姆”)问
jerry::读卡器字符串
jerry=fmap(++“我是jerry”)问
tomAndJerry::读取器字符串
汤姆杰里=(\t j->t++“\n+++j)汤姆杰里
tom
jerry
都是
ask
ing的环境,它们都对环境应用了一个函数。然后,
tomAndJerry
只是通过二进制函数组合它们的一种方式,正如公认的答案所指出的那样

顺便说一下,语言服务器告诉我,
询问
,它允许写

tom::阅读器字符串
汤姆=问(++“我是汤姆。”)

阅读器ra
r->a
同构。因此,您关于“这些函数不接收任何参数”的断言在技术上是正确的,但并不能真正代表事实:此处显示的所有
读取器
操作都接收一个
字符串
参数。哦,因此,该函数中的返回实际上是在实例化读取器monad,我没有意识到我期望收到一些东西作为输出,一个返回,一种转换后的东西作为输出,现在对我来说是有意义的,因为IO非常清楚输入来自哪里,文件和stdin,但是在Reader中呢?它在内存中有一个神奇的对象,可以从中绑定和查找东西?@geckos输入是提供给
runReader-someValueInTheReaderMonad
<代码>x