gpt4 book ai didi

haskell - 如何使用 Supply monad 创建一个生成全局唯一名称的函数?

转载 作者:行者123 更新时间:2023-12-05 00:26:07 30 4
gpt4 key购买 nike

背景:

我正在做一个代码翻译项目,需要我生成变量名。我生成的名字都不应该是重复的。

我真的很沮丧,因为使用 Python 生成器函数会非常简单和优雅。

我试过的:

我之前这样做的方式是通过递归调用我的翻译代码向下传递一个计数器变量,并在基本上每个函数的返回值中传递(可能递增的)计数器。

这真的很困惑:它添加了一个额外的参数来跟踪每个函数;更糟糕的是,它迫使我使用凌乱的元组返回值,否则我会得到一个简单的一元返回值。

在我使用 Haskell 的短暂时间里,我从来没有真正精通过 monad,但我有一种预感,我可以在 State 上使用包装器。 monad 来模拟一个全局计数器变量。在尝试 grok monad 并制作自己的 monad 3 天后,尝试改变其他人的 monad 以生成我需要的值,我终于让自己直接使用其他人的高级 monad(也许有一些改动。)

我现在的问题:

我已经确定了 MonadSupplyMonadUnique作为一对可能提供我需要的简单接口(interface)的模块。不幸的是,我不知道如何使用它们。

特别是 MonadSupply模块文档提供了这个很好的示例用例:

runSupplyVars x = runSupply x vars
where vars = [replicate k ['a'..'z'] | k <- [1..]] >>= sequence

看起来像我想要的!一旦我得到了要编译的模块,我在解释器中检查了这个函数的类型:
> :t runSupplyVars
runSupplyVars :: Supply [Char] a -> Identity (a, [[Char]])

我尝试将很多(值(value)数小时)不同的东西传递给这个函数,但没有成功。我还尝试将函数传递给其他各种函数,以查看它们是否会隐式提供我需要的参数。到目前为止没有运气。

问题:

有人可以提供这个 runSupplyVars 的示例用例吗?功能?

有可能用它做我想做的事吗?我想要一个可以从程序中的任何位置调用的函数,它会在每次调用时为我提供不同的变量名或整数。

最佳答案

实际使用 Supply monad 你应该用 do notation 来构建你的代码并调用supply当你真正需要一个名字时起作用。

例如,这将产生一个以 var_ 为前缀的新变量名。 ,只是为了展示您如何从供应中获取某些东西并使用它:

newVar :: Supply [Char] [Char]
newVar = do
name <- supply
return ("var"_++name)

您需要围绕 Supply 构建整个程序。 monad 然后只调用 runSupplyVars一旦在顶层,否则程序的不同部分将有独立的供应,因此可能会重用相同的变量名。

最后,您需要 runIdentity 来自 Control.Monad.Identity解压 runSupplyVars 的结果进入 (a, [[Char]]) 类型的基础元组,然后丢弃第二个值,它只是未使用名称的(无限)列表。你最好重新定义 runSupplyVars为您执行此操作:
import Control.Monad.Identity

[...]

runSupplyVars :: Supply [Char] a -> a
runSupplyVars x = fst (runIdentity (runSupply x vars))
where vars = [replicate k ['a'..'z'] | k <- [1..]] >>= sequence

这是一个更完整的示例,将它们放在一起。注意 do 使用的不同单子(monad)。使用符号 - IO对于 main函数和 Supply [Char]对于 realProgram并且可能大部分其余代码都在一个更大的版本中:
import MonadSupply
import Control.Monad.Identity

main :: IO ()
main = do
let result = runSupplyVars realProgram
print result

realProgram :: Supply [Char] Int
realProgram = do
x <- newVar
return 0

newVar :: Supply [Char] [Char]
newVar = do
name <- supply
return ("var_"++name)

runSupplyVars :: Supply [Char] a -> a
runSupplyVars x = fst (runIdentity (runSupply x vars))
where vars = [replicate k ['a'..'z'] | k <- [1..]] >>= sequence

关于haskell - 如何使用 Supply monad 创建一个生成全局唯一名称的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22828137/

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