gpt4 book ai didi

haskell - 访问函数中的环境

转载 作者:行者123 更新时间:2023-12-02 02:24:50 24 4
gpt4 key购买 nike

main 中,我可以读取我的配置文件,并将其提供为 runReader (somefunc) myEnv 就可以了。但是 somefunc 不需要访问读取器提供的 myEnv,链中的下一对也不需要。需要 myEnv 中某些内容的函数是一个小叶子函数。

如何在不将所有干预函数标记为 (Reader Env) 的情况下访问函数中的环境?这是不对的,因为否则你一开始就会传递 myEnv 。通过多个级别的函数传递未使用的参数是很丑陋的(不是吗?)。

我可以在网上找到很多示例,但它们似乎都在 runReader 和访问环境之间只有一层。

<小时/>

我接受克里斯·泰勒的,因为它是最彻底的,而且我可以看到它对其他人有用。还要感谢 Heatsink,他是唯一一个尝试直接回答我的问题的人。

对于有问题的测试应用程序,我可能会完全放弃 Reader 并传递环境。它没有给我带来任何东西。

我必须说,我仍然对向函数 h 提供静态数据不仅改变其类型签名,而且改变调用它的 g 和调用 g 的 f 的类型签名的想法感到困惑。尽管涉及的实际类型和计​​算没有改变,但所有这些都是如此。看起来实现细节在代码中到处泄露,但没有带来任何实际好处。

最佳答案

确实为所有内容提供返回类型Reader Env a ,尽管这并不像你想象的那么糟糕。一切都需要这个标签的原因是,如果 f取决于环境:

type Env = Int

f :: Int -> Reader Int Int
f x = do
env <- ask
return (x + env)

g来电 f :

g x = do
y <- f x
return (x + y)

然后g还取决于环境 - y <- f x 行中绑定(bind)的值可能会有所不同,具体取决于传入的环境,因此 g 的适当类型是

g :: Int -> Reader Int Int

这其实是一件好事!类型系统迫使您明确识别函数依赖于全局环境的位置。您可以通过定义短语 Reader Int 的快捷方式来减轻打字的痛苦。 :

type Global = Reader Int

现在你的类型注释是:

f, g :: Int -> Global Int

更具可读性。

<小时/>

替代方法是将环境显式传递给所有函数:

f :: Env -> Int -> Int
f env x = x + env

g :: Env -> Int -> Int
g x = x + (f env x)

这可以工作,事实上,从语法角度来看,它并不比使用 Reader 更糟糕。单子(monad)。当你想要扩展语义时,困难就来了。假设您还依赖于 Int 类型的可更新状态其中计算函数应用程序。现在您必须将功能更改为:

type Counter = Int

f :: Env -> Counter -> Int -> (Int, Counter)
f env counter x = (x + env, counter + 1)

g :: Env -> Counter -> Int -> (Int, Counter)
g env counter x = let (y, newcounter) = f env counter x
in (x + y, newcounter + 1)

这显然不太令人愉快。另一方面,如果我们采用一元方法,我们只需重新定义

type Global = ReaderT Env (State Counter)

f 的旧定义和g继续工作,没有任何麻烦。要更新它们以具有应用程序计数语义,我们只需将它们更改为

f :: Int -> Global Int
f x = do
modify (+1)
env <- ask
return (x + env)

g :: Int -> Global Int
g x = do
modify(+1)
y <- f x
return (x + y)

现在它们工作得很好。比较两种方法:

  • 当我们想要向程序添加新功能时,显式传递环境和状态需要完全重写。

  • 使用单子(monad)接口(interface)需要更改三行 - 即使我们更改了第一行,程序仍然可以继续工作,这意味着我们可以增量地进行重构(并在每次更改后进行测试),从而减少重构引入新错误的可能性。

关于haskell - 访问函数中的环境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11226338/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com