【发布时间】:2021-02-24 11:15:20
【问题描述】:
我正在查看来自JuicyPixels 的一些源代码,可变向量让我感到困惑。在第 808 行的函数 generateMutableImage 中
generateMutableImage :: forall m px. (Pixel px, PrimMonad m)
=> (Int -> Int -> px) -- ^ Generating function, with `x` and `y` params.
-> Int -- ^ Width in pixels
-> Int -- ^ Height in pixels
-> m (MutableImage (PrimState m) px)
{-# INLINE generateMutableImage #-}
generateMutableImage f w h = MutableImage w h `liftM` generated where
compCount = componentCount (undefined :: px)
generated = do
arr <- M.new (w * h * compCount)
let lineGenerator _ !y | y >= h = return ()
lineGenerator !lineIdx y = column lineIdx 0
where column !idx !x | x >= w = lineGenerator idx $ y + 1
column idx x = do
unsafeWritePixel arr idx $ f x y
column (idx + compCount) $ x + 1
lineGenerator 0 0
return arr
我认为generated 是m (Data.Vector.Storable.Mutable.STVector) 类型并且理解它是如何声明的,但我不知道它是如何修改的。
我知道 unsafeWritePixel 是负责这件事的人,但它与 (PrimMonad m) => m monad 有什么关系?
另外,!y 的 ! 是什么意思?这些是一些神奇的运算符或符号吗?
【问题讨论】:
-
!in!y是 bang 模式:downloads.haskell.org/~ghc/7.8.4/docs/html/users_guide/… -
unsafeWritePixel的典型实现将使用thisunsafeWrite。这是unsafeWritePixel和PrimMonad之间的连接。