gpt4 book ai didi

haskell - 使用读取后不变的参数

转载 作者:行者123 更新时间:2023-12-02 06:34:38 26 4
gpt4 key购买 nike

我正在学习 Haskell 并编写程序来解决玩具问题。该程序使用一个参数 k,该参数在运行时不会更改,在从文件中读取参数后。我对使用纯函数还很陌生,我想尽可能多地编写纯函数。

我有一个数据类型 Node,以及用于比较节点、获取节点的后代等的函数。目前,所有这些函数都将参数k 作为参数,例如

compare k node1 node2 = ...
desc k node = ...

每当我必须在函数中递归调用其中任何一个时,我都必须重复 k 参数。这似乎是多余的,因为 k 对于这些函数永远不会有不同的值,而且它使类型签名的可读性降低,如果可能的话,我想重构它。

是否有任何策略可以使用纯函数执行此操作,或者这只是我必须处理的一个限制?

我想到了什么

早些时候,我在顶层硬编码了 k,它似乎可以工作(我能够在函数中使用 k 而无需将它作为显式参数).但是,一旦我需要从文件中读取输入,这显然是不可行的。

另一种可能的策略是在 main 函数中定义所有这些函数,但在 Haskell 中似乎强烈建议不要这样做。

最佳答案

通常的 Haskell 方法是使用 Reader monad。考虑 Reader 的一种方式是,它为计算提供了对环境的访问。可以定义为

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

因此您的函数将具有以下类型

compare :: Node -> Node -> Reader k Ordering -- or Bool, or whatever the return value is

desc :: Node -> Reader k String -- again, guessing at the output type.

Reader 计算中,使用函数 ask::Reader r r 来访问参数。

在顶层,您可以使用 runReader theComputation env 运行 Reader 计算

这通常比显式传递参数更好。首先,任何不需要环境的函数都可以写成普通函数而不用把它作为参数。如果它调用另一个确实使用该环境的函数,monad 将自动提供它,您无需做任何额外的工作。

你甚至可以定义一个类型同义词,

type MyEnv = Reader Env

并将其用于您的函数类型签名。然后如果你需要改变环境,你只需要改变一种类型而不是改变你所有的类型签名。

来自 standard libraries 的定义处理 monad 转换器有点复杂,但它的工作方式与这个更简单的版本相同。

关于haskell - 使用读取后不变的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22573397/

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