Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.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_Monads_Reader Monad - Fatal编程技术网

Haskell 我知道如何使用它,但我不知道;我不能确切地理解它是如何做到的(读者monad)

Haskell 我知道如何使用它,但我不知道;我不能确切地理解它是如何做到的(读者monad),haskell,monads,reader-monad,Haskell,Monads,Reader Monad,考虑以下代码(忽略明显的部分) 函数“calculateContentLength”具有返回类型(类型为Reader String Int),但没有传入参数。我意识到函数本身只是传递给runReader函数的两个参数之一,但是runReader的第二个参数“s”如何与“calculateContentLength”中的“ask”绑定 换句话说,“calculateContentLength”如何“知道”(并访问)使用“runReader”传递的第二个参数?让我们看看定义读取器的一种方法 newt

考虑以下代码(忽略明显的部分)

函数“calculateContentLength”具有返回类型(类型为Reader String Int),但没有传入参数。我意识到函数本身只是传递给runReader函数的两个参数之一,但是runReader的第二个参数“s”如何与“calculateContentLength”中的“ask”绑定


换句话说,“calculateContentLength”如何“知道”(并访问)使用“runReader”传递的第二个参数?

让我们看看定义
读取器的一种方法

newtype Reader r a = Reader { runReader :: r -> a }
所以
Reader
是一个接受函数的构造函数。该函数接受类型为
r
的环境,并返回类型为
a
的结果

ask = Reader { runReader = \env -> env }
ask = Reader id
return
操作只是忽略环境并返回一个值

return x = Reader { runReader = \_ -> x }
m>>=n
操作执行简单的排序:它获取环境,在该环境中运行
m
,然后在同一环境中运行
n
,并将
m
的结果传递给它

m >>= n = Reader $ \env -> let
  a = runReader m env
  in runReader (n a) env
现在我们可以拿你的例子,去糖,一步一步地减少

calculateContentLength = do
  content <- ask
  return (length content)

-- substitute definition of 'ask'

calculateContentLength = do
  content <- Reader id
  return (length content)

-- substitute definition of 'return'

calculateContentLength = do
  content <- Reader id
  Reader (\_ -> length content)

-- desugar 'do' into '>>='

calculateContentLength =
  Reader id >>= \content -> Reader (\_ -> length content)

-- definition of '>>='

calculateContentLength = Reader $ \env -> let
  a = runReader (Reader id) env
  in runReader ((\content -> Reader (\_ -> length content)) a) env

-- reduce lambda

calculateContentLength = Reader $ \env -> let
  a = runReader (Reader id) env
  in runReader (Reader (\_ -> length a)) env

-- definition of 'runReader'

calculateContentLength = Reader $ \env -> let
  a = id env
  in runReader (Reader (\_ -> length a)) env

-- definition of 'id'

calculateContentLength = Reader $ \env -> let
  a = env
  in runReader (Reader (\_ -> length a)) env

-- remove redundant variable

calculateContentLength = Reader $ \env
  -> runReader (Reader (\_ -> length env)) env

-- definition of 'runReader'

calculateContentLength = Reader $ \env -> (\_ -> length env) env

-- reduce

calculateContentLength = Reader $ \env -> (length env)
calculateContentLength = Reader length
calculateContentLength=do
内容>=\content->Reader(\\内容->长度)
--“>>=”的定义
calculateContentLength=Reader$\env->let
a=runReader(读卡器id)环境
在runReader((\content->Reader(\ \ \ \->length content))a)环境中
--降低λ
calculateContentLength=Reader$\env->let
a=runReader(读卡器id)环境
在runReader(读卡器(\ \ \->长度a))环境中
--“runReader”的定义
calculateContentLength=Reader$\env->let
a=id环境
在runReader(读卡器(\ \ \->长度a))环境中
--“id”的定义
calculateContentLength=Reader$\env->let
a=环境
在runReader(读卡器(\ \ \->长度a))环境中
--删除冗余变量
calculateContentLength=读取器$\env
->runReader(读卡器(\ \ \->length env))env
--“runReader”的定义
calculateContentLength=Reader$\env->(\ \ \ \->length env)env
--减少
calculateContentLength=读取器$\env->(长度env)
calculateContentLength=读卡器长度
现在应该更容易看到
runReader calculateContentLength
length
是如何相同的,以及
ask
是如何不神奇的monad的
>=
操作构建了一个函数,当您使用
runReader
运行计算时,它会隐式地为您传递环境

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

实际上,
Reader
是根据
ReaderT
定义的,它使用一元操作而不是纯函数,但其实现形式基本相同。

顺便说一句,我肯定会涉及到咖喱,但我只是看不清楚细节。我鼓励您使用
runReader
ask
的源代码来证明简单的等式
runReader ask s=s
。然后看看你是否可以用这个证明作为直觉的燃料。谢谢你——我完全忘记了函数开头的“do”。所以我错过了整个装订部分。这就是为什么我看不到发生了什么。谢谢你的详细解释。
calculateContentLength = do
  content <- ask
  return (length content)

-- substitute definition of 'ask'

calculateContentLength = do
  content <- Reader id
  return (length content)

-- substitute definition of 'return'

calculateContentLength = do
  content <- Reader id
  Reader (\_ -> length content)

-- desugar 'do' into '>>='

calculateContentLength =
  Reader id >>= \content -> Reader (\_ -> length content)

-- definition of '>>='

calculateContentLength = Reader $ \env -> let
  a = runReader (Reader id) env
  in runReader ((\content -> Reader (\_ -> length content)) a) env

-- reduce lambda

calculateContentLength = Reader $ \env -> let
  a = runReader (Reader id) env
  in runReader (Reader (\_ -> length a)) env

-- definition of 'runReader'

calculateContentLength = Reader $ \env -> let
  a = id env
  in runReader (Reader (\_ -> length a)) env

-- definition of 'id'

calculateContentLength = Reader $ \env -> let
  a = env
  in runReader (Reader (\_ -> length a)) env

-- remove redundant variable

calculateContentLength = Reader $ \env
  -> runReader (Reader (\_ -> length env)) env

-- definition of 'runReader'

calculateContentLength = Reader $ \env -> (\_ -> length env) env

-- reduce

calculateContentLength = Reader $ \env -> (length env)
calculateContentLength = Reader length