全局变量和读者monad

J F*_*sch 5 haskell

我有一个模块,通过调用初始化函数创建并初始化全局环境(定义某些约束,如邻居IP地址等).许多后续函数在调用时应使用这些约束.

虽然原则上我理解读者monad的作用,但我不太确定如何将其应用于我的问题,尤其是.

  • 它如何用于初始化由用户定义并作为数据/参数传递给初始化函数的环境.我的意思是,读者monad必须从某个地方获得构成全局不可变环境的实际值.我希望从初始化函数调用中读取值,如下所示myinitial :: arg1 -> arg1 -> IOString,arg1arg2通过reader monad(?)成为后续函数可访问的全局不可变数据

  • 我如何将这些环境值用作函数参数,例如recvFrom s arg1,arg1来自我的环境的全局不可变数据.要么if arg2 > arg1 then ... else ...

我当然可以制作一个配置文件,但我觉得配置文件会带来很大的灵活性.

[编辑]我理解问题,但是不应该有额外的"无点类似"方式,以便如果函数签名被定义正确,可以省略全局/环境不可变吗?我怎么会需要重构我的if-then-else来应用.

Sco*_*est 5

您可以通过检查askrunReader函数的类型和文档来回答大多数问题.

一,ask:

ask :: Reader m r => m r
Run Code Online (Sandbox Code Playgroud)

这将返回包含在monad中的基础只读数据.很酷,所以当你想将它与其他函数一起使用时,你将如何进入状态,在上面的例子中:

do x <- ask
   recvFrom s x
Run Code Online (Sandbox Code Playgroud)

(recvFrom当然,取决于类型)

接下来是runReader,这是你如何给它你正在谈论的初始数据.它基本上只是Reader使用它给出的数据运行计算:

runReader :: Reader r a -> r -> a
Run Code Online (Sandbox Code Playgroud)

这意味着:使用类型的只读数据r(第二个参数)运行计算(第一个参数).它最终将返回第一个参数的结果类型a.在您的情况下,这可能看起来像:

result = runReader computationUsingArg1Arg2 (arg1, arg2)
Run Code Online (Sandbox Code Playgroud)

然后在里面computationUsingArg1Arg2你可以阅读arg1arg2通过ask.


Chr*_*lor 4

这是一个可以澄清问题的例子。首先需要导入 Reader 模块:

import Control.Monad.Reader
Run Code Online (Sandbox Code Playgroud)

现在让我们定义一些数据结构(我们将用它来保存姓名和年龄)

data Config = Config { name :: String, age :: Int }
Run Code Online (Sandbox Code Playgroud)

现在定义一个在 Reader monad 中工作的函数(它的类型是Reader Config (String, Int),但我们不需要指定 - 它可以被推断)。该函数所做的只是询问环境(类型为Config),然后提取字段并用它们执行某些操作。

example = do
    c <- ask
    return ("Hello " ++ name c, 2 * age c)
Run Code Online (Sandbox Code Playgroud)

现在我们将它们全部整合到一个程序中。do 块之后的前四行允许用户输入他们的姓名和年龄。然后我们Config使用用户的输入构建一个结构(我们必须使用read将变量_age,即 a String,转换为 an ,Int以便我们可以将其提供给Config构造函数)并example使用该函数在此环境中执行runReader。最后,我们使用计算结果来生成一些输出。

main = do
    putStrLn "Enter your name:"
    _name <- getLine
    putStrLn "Enter your age:"
    _age <- getLine
    let config = Config _name (read _age)
    let result = runReader example config
    putStrLn $ fst result
    putStrLn $ "Twice your age is: " ++ show (snd result)
Run Code Online (Sandbox Code Playgroud)