import Control.Monad
import Control.Monad.Random as MR
import Control.Monad.ST
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import qualified Data.Vector as V
import qualified Data.Vector.Generic as VG
import Data.Vector.Generic.Mutable as VGM
import qualified Data.Vector.Unboxed as VU
data Obj m = Obj
{ aNum :: Int
, vec :: m (VU.Vector Int)
}
instance Show (Obj m) where
show Obj{ aNum = a
, vec = v
} = show a ++ show v -- 'show v' not OK
main :: IO()
main = do
rVec <- evalRandIO (randVector 5) -- OK
obj <- evalRandIO (newObj 1 5) -- Not OK
print $ show rVec
print $ show obj
newObj :: (MonadRandom m) => Int -> Int -> Obj m
newObj aNum' vecLen = Obj aNum' $ randVector vecLen
randVector :: (MonadRandom m) => Int -> m (VU.Vector Int)
randVector len = randSample (VU.enumFromN 0 len) $ VG.length vec
-- Fisher-yates shuffle
randSample :: (MonadRandom m, (VG.Vector v a)) => v a -> Int -> m (v a)
randSample vec len = do
let getR i = do
r <- getRandomR (i, (VG.length vec)-1)
return (i, r)
swaps <- mapM getR [0..len-1]
let vec_rands = runST $ do
vec_mut <- VG.thaw vec
forM_ swaps $ \(i, j) -> do
VGM.swap vec_mut i j
vec_rands' <- VG.unsafeFreeze vec_mut
return vec_rands'
return $ VG.take len vec_rands
我在使用monad创建数据结构时遇到了一些麻烦。特别是,数据结构包含一个随机向量和一些其他非随机字段。evalRandIO
当整个类型是monad时,使用工作原理,而当数据结构的仅一部分是monad时,则不能工作。
我感觉应该使用fmap
或类似的东西,但是它们会给出不同的错误。为了将随机矢量打印到屏幕上,我也遇到了麻烦。我不确定之间的差异Rand g
和MonadRandom m
哪一个我应该使用,和。后者似乎有效,但所有在线示例似乎都在使用Rand g
。此外。一般代码审查也表示赞赏。
* Couldn't match type `Obj m1' with `RandT StdGen Data.Functor.Identity.Identity a0' Expected type: Rand StdGen a0 Actual type: Obj m1 * In the first argument of `evalRandIO', namely `(newObj 1 5)' In a stmt of a 'do' block: obj <- evalRandIO (newObj 1 5) In the expression: do { rVec <- evalRandIO (randVector 5); obj <- evalRandIO (newObj 1 5); print $ show rVec }
newObj :: (MonadRandom m) => Int -> Int -> Obj m
newObj 1 4 :: (MonadRandom m) => Obj m
evalRandIO :: Rand StdGen a -> IO a
evalRandIO (newObj 1 4) :: -- ?????????
问题Obj m
是不是Rand StdGen a
。因此,您不能使用evalRandIO
。
但是,放入m
内部并没有任何意义Obj
。有可能,但不是很方便。如果我们已经使用过,我们可以修复您的代码
evalObj :: Obj m -> IO (Int, (VU.Vector Int))
evalObj (Obj a mvec) = do
uvec <- evalRandIO mvec
return (a, uvec)
但这仍然不容易使用。相反,让我们简化一下Obj
:
data Obj = Obj { oNum :: Int, oVec :: VU.Vector Int } deriving (Eq, Show)
现在让我们重写newObj
,以便它返回m Obj
:
newObj :: (MonadRandom m) => Int -> Int -> m Obj
newObj num len = Obj num `fmap` randVector len
-- alternatively, but does the same:
newObj num len = do
vec <- randVector len
return (Obj num vec)
一切都很好。这也使您可以使用Obj
不知道您在中操作的in函数MonadRandom
,例如
sqObj :: Obj -> Obj
sqObj (Obj a v) = Obj (a * a) (VU.map (^2) v)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句