【发布时间】:2015-12-21 03:31:11
【问题描述】:
我正在尝试使用 Haskell + Netwire 5 (+ SDL) 创建游戏。现在我正在处理输出部分,我想创建在某些游戏状态下读取的连线,并将 SDL 表面输出到屏幕上。
但是,问题在于 SDL 表面包含在 IO monad 中,因此创建此类表面的任何函数都必须具有类型 a -> IO b。当然,arr 不会从a -> m b 构造一个Wire。但是,由于线的类型签名是(Monad m, Monoid e) => Wire s e m a b,它看起来很像 Kleisi Arrow,但我找不到合适的构造函数来制作这样的线。
我是 FRP 和 Arrows 的新手,并且没有在 Haskell 中进行过很多编程,所以这可能不是实现图形输出的最佳方式。如果我从一开始就错了,请告诉我。
一些SDL功能相关:
createRGBSurfaceEndian :: [SurfaceFlag] -> Int -> Int -> Int -> IO Surface
fillRect :: Surface -> Maybe Rect -> Pixel -> IO Bool
blitSurface :: Surface -> Maybe Rect -> Surface -> Maybe Rect -> IO Bool
flip :: Surface -> IO ()
更新 1
此代码类型检查,但现在我正在尝试将其与 SDL 接口以进行测试
wTestOutput :: (Monoid e) => Wire s e IO () SDL.Surface
wTestOutput = mkGen_ $ \a -> (makeSurf a >>= return . Right)
where
makeSurf :: a -> IO SDL.Surface
makeSurf _ = do
s <- SDL.createRGBSurfaceEndian [SDL.SWSurface] 800 600 32
SDL.fillRect s (Just testRect) (SDL.Pixel 0xFF000000)
return s
testRect = SDL.Rect 100 100 0 0
【问题讨论】:
-
显然您已经回答了自己的问题。将其作为答案,而不是将其添加到您的问题中。 (特别是,提及
mkGen_可能就足够了,它是答案中的类型,对于未来的读者来说,特定的实现可能不太有趣)。如果您有更多问题,请单独提问,而不是更改您的问题。 -
不,我还没有验证它是否有效
-
现在我用
putStrLn作为一个更简单的例子进行了验证。 -
电线和 FRP 通常是对时变值进行建模的一种方式。他们不应该真正“创造”任何东西。正如您编写的那样,您的程序将在每次评估电线时创建一个新的 SDL 表面!
-
之前未使用的表面会被垃圾回收吗?当然,从语义上讲,更新同一个表面是一样的(无论如何都是状态),但我认为这些是实现细节。
标签: haskell functional-programming frp arrows netwire