gpt4 book ai didi

c - Haskell:使用对变量的最后引用来有效地创建一个新变量

转载 作者:太空狗 更新时间:2023-10-29 17:03:08 25 4
gpt4 key购买 nike

这段 C 代码在概念上可以描述为创建一个与输入数组相同但第一个元素为 1 的新数组:

int* retire_and_update(int* arr) {
arr[0] = 1;
return arr;
}

只要不进一步引用输入数组及其元素,这是一个纯函数(wink wink nudge nudge)。 C 类型系统不会为我们强制执行,但原则上它似乎是强制执行的。

gcc 生成的代码简单高效:

retire_and_update:
movq %rdi, %rax
movl $1, (%rdi)
ret

我们的函数通过在常数时间内创建一个全新的数组并且不使用额外的内存来实现看似不可能的事情。好的。是否可以编写一个具有类似数组输入和输出的 Haskell 函数,该函数可以用类似的代码有效地实现?有没有一种方法可以表达“这是对该变量的最后一次引用”,以便纯函数可以在幕后蚕食该变量?

如果函数被内联,那么这里不需要发生任何有趣的事情,所以我们假设调用者和函数将被单独编译。

最佳答案

虽然ST monad 您所描述的,实际上您可以使用 STUArray 实现大部分内容.因此,您的代码模型可能类似于:

import Control.Monad (forM_)
import Control.Monad.ST (ST)
import Data.Array.Unboxed (UArray)
import Data.Array.ST (STUArray, newArray, readArray, writeArray, runSTUArray)

retire_and_update :: STUArray s Int Int -> ST s (STUArray s Int Int)
retire_and_update arr = do
writeArray arr 0 1
return arr

如果您有另一个函数可以就地改变数组,例如:

mutate_inplace :: STUArray s Int Int -> Int -> ST s ()
mutate_inplace arr size = do
forM_ [2..size - 1] $ \i -> do
a <- readArray arr (i - 2)
b <- readArray arr (i - 1)
writeArray arr i (a + b)

您可以这两个非纯函数绑定(bind)在一起,然后使用 runSTUArray在纯函数中调用它们:

run :: Int -> UArray Int Int
run size = runSTUArray $ do
arr <- newArray (0, size - 1) 0
retire_and_update arr
mutate_inplace arr size
return arr

请注意 run 保持纯净,返回数组的早期版本不会泄露到任何地方:

\> run 8
array (0,7) [(0,1),(1,0),(2,1),(3,1),(4,2),(5,3),(6,5),(7,8)]

关于c - Haskell:使用对变量的最后引用来有效地创建一个新变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33820971/

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