2016-05-15 33 views
3

我要創建通過N.包含數字1的隨機排列據我瞭解一個列表,可以在使用VUM.swap runST,但因爲我需要隨機數字,所以我想我可能會在IO monad中執行這兩個操作。創建1..N的隨機排列與Data.Vector.Unboxed.Mutable

下面產率的代碼:

預期類型:IO(VU.Vector智力),實際類型:IO(VU.Vector (VU.Vector A0))

爲返回語句。

import qualified Data.Vector.Unboxed   as VU 
import qualified Data.Vector.Unboxed.Mutable as VUM 
import   System.Random 

randVector :: Int -> IO (VU.Vector Int) 
randVector n = do 
    vector <- VU.unsafeThaw $ VU.enumFromN 1 n 
    VU.forM_ (VU.fromList [2..VUM.length vector]) $ \i -> do 
    j <- randomRIO(0, i) :: IO Int 
    VUM.swap vector i j 
    return $ VU.unsafeFreeze vector 

我不太清楚爲什麼返回向量是嵌套的。我需要使用VU.fold1M_嗎?

回答

3

unsafeFreeze vector已經返回IO (VU.Vector Int)。只需將最後一行更改爲VU.unsafeFreeze vector即可。

在另一個說明中,您應該迭代到VUM.length vector - 1,因爲[x .. y]randomRIO都使用包含範圍。此外,您可以在此處使用普通的forM_進行迭代,因爲您只關心副作用。

import   Control.Monad 
import qualified Data.Vector.Unboxed   as VU 
import qualified Data.Vector.Unboxed.Mutable as VUM 
import   System.Random 

randVector :: Int -> IO (VU.Vector Int) 
randVector n = do 
    vector <- VU.unsafeThaw $ VU.enumFromN 1 n 
    forM_ [2..VUM.length vector - 1] $ \i -> do 
    j <- randomRIO(0, i) :: IO Int 
    VUM.swap vector i j 
    VU.unsafeFreeze vector 

我看着生成的代碼,它似乎與GHC 7.10.3 forM_編譯成一個有效的循環,而VU.forM_保留了中間列表,肯定是顯著慢(這是我的forM_預期結果,但我不確定VU.forM_)。

+0

這個伎倆!返回聲明是問題。如何使用返回嵌套向量?我永遠不會想到這一點。我使用'VU.forM_'而不是普通版本,因爲我不確定普通版本的位置。典型的輸入大小是n = 50,並建立5000 randVectors,我無法想象不同的循環會有很多秒不同。 – tsorn

+0

我在'forM_'範圍內添加了一條評論,並編輯了'forM_'性能的位。 –

1

我想嘗試(在注完更新):

import Control.Monad 

randVector :: Int -> IO (VU.Vector Int) 
randVector n = do 
    vector <- VU.unsafeThaw $ VU.enumFromN 1 n 
    forM_ [2..VUM.length vector] $ \i -> do 
    j <- randomRIO(0, i) :: IO Int 
    VUM.swap vector i j 
    return $ VU.unsafeFreeze vector 

編輯:爲@安德拉斯·科瓦克斯指出的那樣,你不希望return末所以最後一行應該是:

VU.unsafeFreeze vector