问题:
如何为需要“SDL.Surface”的函数提供“IO SDL.Surface”?
我宁愿重新考虑我的整个方法而不是使用类似“unsafePerformIO”的东西,除非这实际上是使用它的正确时间(我怀疑)。
更多信息:
我有一个充满数字和文件路径的文件,我已经解析了这个文件并将位于这些路径的图像加载到列表[(Int,IO SDL.Surface)]中。问题是,SDL.blitSurface函数需要正常的SDL.Surface。
错误讯息:
Couldn't match type `IO SDL.Surface'
with `GHC.ForeignPtr.ForeignPtr SDL.SurfaceStruct'
Expected type: SDL.Surface
Actual type: IO SDL.Surface
我不确定是否有必要使用源代码来回答这个问题,但我会提供一些代码,以防它有所帮助:
要加载我使用的图像文件:
loadImage :: FilePath -> IO SDL.Surface
loadImage [] = error "empty list"
loadImage a =
SDL.loadBMP a
创建我使用的数字和图像列表:
createIDImageList :: [Tiletype] -> [(Int, IO SDL.Surface)]
createIDImageList a =
if null a then []
else [(tiletypeid $ a !! 0, loadImage (C8.unpack ( tiletypeimage ( a !! 0))))] ++ createIDImageList (tail a)
要从此列表中检索正确的图片,我使用此功能:
imageFromID :: Int -> [(Int, IO SDL.Surface)] -> Maybe (IO SDL.Surface)
imageFromID a b =
if null b then Nothing
else if a == (fst $ b !! 0) then Just (snd $ b !! 0)
else imageFromID a (tail b)
最后我使用带有SDL.blitSurface的imageFromID来绘制图像,但我不能因IO而使用。
答案 0 :(得分:2)
如果您最终得到[IO Foobar]
,那么可能想要的内容实际上是IO [Foobar]
。 sequence
函数将一个转换为另一个。或者,您可以在首先创建列表时使用mapM
代替map
。
在你的例子中,它有点复杂,因为我们有[(Int, IO Surface)]
。让我看看我能提出什么建议......
loadImage
是一个I / O操作。它需要一个文件名并返回一个IO动作来加载图像。您的createIDImageList
功能确实是
createIDImageList = map f
where
f a = (tiletypeid a, loadImage (C8.unpack ( tiletypeimage a) ) )
您可能要做的是将f
更改为IO (Int, Surface)
而不是(Int, IO Surface)
。然后你可以mapM f
,产生一个返回一个东西列表的I / O动作。
createIDImageList :: [Tiletype] -> IO [(Int, SDL.Surface)]
createIDImageList = mapM f
where
f a = do
surface <- loadImage (C8.unpack (tiletypeimage a) )
return (tiletypeid a, surface)
关于imageFromID
:您可能想要做的事情是这样的:
main = do
images <- createIDImageList (...)
...
let image5 = imageFromID 5 images
SDL.blitSurface image5 ...
然后imageFromID
的类型变为
imageFromID :: `Int -> [(Int, SDL.Surface)] -> Maybe SDL.Surface
(因为images
现在有[(Int, SDL.Surface)]
类型,其中没有IO
,感谢<-
。)
你在这里做的是createIDImageList
实际上是从磁盘上加载所有内容,然后你可以使用imageFromID
(其中没有I / O),只要你想获得表面你对此感兴趣。
答案 1 :(得分:0)
do image <- loadImage "imagefile"
blitSurface image rect1 dest rect2