gpt4 book ai didi

haskell - 向量的单次创建(或 : can someone type annotate this for me? )

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

作为 this Redddit sub-thread 的一部分,我遇到了以下代码片段讨论 Fisher-Yates 洗牌的实现:

randomIs g n = fill g 0
where
v = enumFromN 0 n

fill g i = when (i < n) $ do
let (x,g') = randomR (i, n-1) g
G.swap v i x
fill g' (i+1)

(我猜 G 指的是 Data.Vector.Generic.Mutable...对吧?)。以前从未以单子(monad)方式创建向量,我很难理解这一点,尤其是在没有类型注释的情况下。 v 不是 Data.Vector Int 类型吗?那怎么可以将它传递给 G.swap 呢?不是要先解冻吗?

我可能只是误解了 Data.Vector.Generic,但如果有人可以澄清以上内容(也许通过添加类型注释?),我将不胜感激。

附录:这是我自己添加类型注释的尝试:

import qualified Data.Vector.Unboxed as UVect
import qualified Data.Vector.Unboxed.Mutable as UMVect
import qualified System.Random as R
import Control.Monad
import Control.Monad.ST

randomPermutation :: forall a. (R.RandomGen a) => a -> Int -> UVect.Vector Int
randomPermutation g n = runST newVect
where
newVect :: ST s (UVect.Vector Int)
newVect = UVect.unsafeThaw (UVect.enumFromN 0 n) >>= \v ->
fill v 0 g >>
UVect.unsafeFreeze v

fill x i gen = when (i < n) $
let (j, gen') = R.randomR (i, n-1) gen in
UMVect.unsafeSwap x i j >>
fill x (i+1) gen'

如您所见,我正在避免使用 Data.Vector.Generic 来排除可能由于未正确理解而导致的错误源。我也在 ST monad 中做事。

在我看来,fill 的类型应该是

UMVect.MVector (ST s (UVect.Vector Int)) Int -> Int -> a -> ST s ()

但是 GHC 反对。有什么提示吗?再次说明:如果我不注释 fill,它会进行类型检查。

旁注:我还希望 randomPermutation 返回更新后的随机数生成器。因此,我还需要 fill 来处理生成器的状态。由于我目前的类型混淆,我不知道如何巧妙地做到这一点。有什么提示吗?

最佳答案

编译错误告诉我们:

Expected type: ST s (UMVect.MVector (ST s (UVect.Vector Int)) Int)
Actual type: ST s (UMVect.MVector (Control.Monad.Primitive.PrimState (ST s)) Int)

因此,将 fill 的类型签名更改为 UMVect.MVector (PrimState (ST s)) Int -> Int -> a -> ST s () (也添加 import Control.Monad.Primitive)解决了问题!

关于haskell - 向量的单次创建(或 : can someone type annotate this for me? ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7751556/

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