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
Haskell 读者如何理解monad';s";询问;功能工作?_Haskell - Fatal编程技术网

Haskell 读者如何理解monad';s";询问;功能工作?

Haskell 读者如何理解monad';s";询问;功能工作?,haskell,Haskell,我在理解这段代码是如何工作的方面有问题。特别是,ask如何知道环境在哪里(在我们的例子中就是Int) 更确切地说:我是一个命令式程序员,用这种语言很容易。方法可以在任何对象上调用,比如:obj.f(),或者当我们希望函数使用外部数据时,我们必须通过参数传递数据。这就是读卡器monad所做的;它提供了一个ask函数,可以“神奇地”从稀薄的空气中弹出一个值。要实际使用它,您需要调用runReader,并为其提供Int环境。然后,读卡器类型会自动将该信息从runReader调用传播到每个ask调用。简

我在理解这段代码是如何工作的方面有问题。特别是,
ask
如何知道环境在哪里(在我们的例子中就是
Int


更确切地说:我是一个命令式程序员,用这种语言很容易。方法可以在任何对象上调用,比如:
obj.f()
,或者当我们希望函数使用外部数据时,我们必须通过参数传递数据。

这就是读卡器monad所做的;它提供了一个
ask
函数,可以“神奇地”从稀薄的空气中弹出一个值。要实际使用它,您需要调用
runReader
,并为其提供
Int
环境。然后,
读卡器
类型会自动将该信息从
runReader
调用传播到每个
ask
调用。

简短的波浪式回答。
Reader Int(T Int)
值本质上只是一个类型为
Int->(T Int)
的包装函数。为了运行该函数,我们首先需要提取它。我们使用
runReader
来实现这一点

data T b = E | N b (T b) (T b) 


f :: T b -> Reader Int (T Int)
f (N i l r) = ask >>= \x ->  local ((-)4) (f l) >>= \l' -> local ((-)1) (f r) >>= \r' -> return (N x l' r')
f E = return E
(通常,您只需编写
print$runReader(f tree)20
;我将其拆分以对应下面的粗略类比。)

ask
(由
monader
typeclass定义,并由用于定义
读取器
类型的
ReaderT
monad转换器实现)基本上检索传递给
h
的参数值


从某种意义上说,
Reader Int(T Int)
是一个包含调用函数
ask
的函数
g
的对象
runReader g
创建一个新函数,当调用该函数时,该函数定义一个函数
ask
,该函数只返回其参数,然后调用
g
。现在当
g
调用
ask
时,它会返回最初传递给
h
的参数。这可能是我本周看到的关于二叉树和读卡器单子()的第二个或第三个问题。它是来自MOOC课程作业还是什么?“Reader Int(T Int)值本质上只是Int->(T Int)类型的一个封装函数”这对我来说并不明显,请解释:)我本来打算尝试一下,但也许最好让你看看。它直接定义
读取器
monad,而不是从应用于标识monad的转换器(实现类型类)构建它。
data T b = ... deriving (Show)

main = let tree = (N 10 (N 8 E E) E)
           g = f tree
           h = runReader g
       in print $ h 20