gpt4 book ai didi

haskell - 'do' 表示法中的新范围

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

我正在尝试编写一个递归函数来改变 Data.Vector.Unboxed.Mutable 'Vector',但我认为这个问题适用于任何 monadic 代码。

举个例子:

import Data.Vector.Unboxed as U
import Data.Vector.Unboxed.Mutable as M
import Control.Monad
import Control.Monad.ST
import Control.Monad.Primitive

f :: U.Vector Int -> U.Vector Int
f x = runST $ do
y <- U.thaw x
add1 y 0
U.freeze y

add1 :: (PrimMonad m) => MVector (PrimState m) Int -> Int -> m()
add1 v i | i == M.length v = return ()
add1 v i = do
c <- M.unsafeRead v i
M.unsafeWrite v i (c + 1)
add1 v (i+1)

但是,v 在每次递归调用中都不会改变。我希望能够删除 v 作为函数的参数并将“add1”内联到 f 中,但我需要“y”在范围内。

我可以更进一步,方法是更改​​ add1(并保持 f 不变),这样 v 就不会在递归中传递:

add1 :: (PrimMonad m) => MVector (PrimState m) Int -> m()
add1 v = do add1_ 0
where len = M.length v
add1_ i | i == len = do return ()
add1_ i = do
x <- M.unsafeRead v i
M.unsafeWrite v i (x + 1)
add1_ (i+1)

不过,我真正想要的是完全内联 add1。这是一个尚未完全编译的解决方案:

f x = let len = U.length x
y = U.thaw x
add1 i | i == len = return ()
add1 i = do
y' <- y
c <- M.unsafeRead y' i
M.unsafeWrite y' i (c+1)
add1 (i+1)
in runST $ do
add1 0
y' <- y
U.freeze y'

GHC 错误:

couldn't match type 'm0' with 'ST s'
couldn't match type 's' with 'PrimState m0'

撇开错误不谈,这还不是最优的:我不想在每个 do 语句中都执行 (y' <- y) (尤其是当 add1 是递归的时候)。我真的很希望 y'(y 的“非单子(monad)”版本)在范围内。有什么办法吗?

(如果我以某种方式严重滥用 monad,我深表歉意)

最佳答案

这个怎么样?

f :: U.Vector Int -> U.Vector Int
f x = runST $ do
y <- U.thaw x
let add1 i | i == length x = return ()
| otherwise = do
c <- M.unsafeRead y i
M.unsafeWrite y i (c+1)
add1 (i+1)
add1 0
U.freeze y

关于haskell - 'do' 表示法中的新范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11641313/

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