我想将一些像素写入图像,并将图像写入磁盘。我一直在遵循我从许多 Haskeller 那里听到的建议来遵循类型签名,并且基本上玩“类型俄罗斯方块”,直到我到达我要去的地方。它主要为我工作,但我遇到了一些麻烦。
要写一个像素,有一个函数:
writePixel :: PrimMonad m => MutableImage (PrimState m) a -> Int -> Int -> a -> m ()
我可以通过阅读签名告诉我需要将 MutableImage 传递给它,所以我寻找一个带有 MutableImage 的函数:
createMutableImage :: (PrimMonad m, Pixel px) => Int -> Int -> px -> m (MutableImage (PrimState m) px)
这似乎在某种状态单子中运行。
writeIt = runST $ createMutableImage 100 100 (100::Pixel8) >>=
freezeImage
这有效,并返回我可以写入磁盘的漂亮灰色图像。但我不知道如何获取 MutableImage 以便我可以将像素写入它!简单地插入 writePixel 调用会给我一个我无法弄清楚的错误:
writeIt = runST $ createMutableImage 100 100 (100::Pixel8) >>=
writePixel 100 100 255 >>=
freezeImage
结果是:
Couldn't match type `MutableImage (PrimState (GHC.ST.ST s)) px0'
with `()'
Expected type: () -> GHC.ST.ST s (Image px0)
Actual type: MutableImage (PrimState (GHC.ST.ST s)) px0
-> GHC.ST.ST s (Image px0)
In the second argument of `(>>=)', namely `freezeImage'
In the second argument of `($)', namely
`createMutableImage 100 100 (100 :: Pixel8)
>>= writePixel 100 100 255
>>= freezeImage'
In the expression:
runST
$ createMutableImage 100 100 (100 :: Pixel8)
>>= writePixel 100 100 255
>>= freezeImage
我可以从 writePixel 签名中看出我缺少 writePixel 的第一个参数。如何获得对 MutableImage 的引用,以便我可以写入它?更重要的是,我如何在这个 monad 中的类型上找到立足点,以便我自己解决这些问题?