与我最近关于处理大数据块的问题密切相关,我已经到了需要获取一个大的不可变数据块,使其对某些操作可变,然后在完成后再次使其不可变的地步。
由于我想至少保留纯洁的外观,可变数据将是原始不可变数据的可变副本。作为参考,我正在查看 Real World Haskell 中的Bloom Filter示例,但发现我实际上无法让我的代码在 runST 中运行。
我的数据结构,首先是纯的,然后是不纯的:
import Data.Vector.Unboxed (Vector)
import Data.Vector.Unboxed.Mutable (MVector)
data PixelMap = Bitmap Int Int (Vector Bool)
data MPixelMap s = MBitmap Int Int (MVector s Bool)
然后我只创建了一个基本的 newBitmapM 函数:
newBitmapM :: (Int, Int) -> ST s (MPixelMap s)
newBitmapM (width, height) = MBitmap width height `liftM` MV.replicate (width * height) False
这可以很好地加载到 GHCI 中,但随后我尝试运行它:
> runST $ newBitmapM (15, 15)
<interactive>:78:9:
Couldn't match type `a' with `PixelMapMutable s'
`a' is a rigid type variable bound by
the inferred type of it :: a at <interactive>:78:1
Expected type: ST s a
Actual type: ST s (PixelMapMutable s)
In the return type of a call of `newBitmapM'
In the second argument of `($)', namely `newBitmapM (15, 15)'
In the expression: runST $ newBitmapM (15, 15)
这个错误信息对我来说毫无意义。 a
, 在类型中定义的 forrunST
应该是多态的,因此根本不是“固定的”。任何人都可以对此进行解码以告诉我代码到底有什么问题吗?