如何避免在整个程序中使用IO monad?

Ben*_*ach 6 io haskell

我正在使用Gloss库在Haskell中编写一个Sokoban程序,当达到一个级别时,我达到了我想要的程度,从文本文件加载到一个新的级别并让程序继续.

由于Gloss的限制,我对此有一点困难 - play设置游戏并让它不断更新的功能如下所示:

play    :: forall world
        .  Display                      -- ^ Display mode.
        -> Color                        -- ^ Background color.
        -> Int                          -- ^ Number of simulation steps to take for each second of real time.
        -> world                        -- ^ The initial world.
        -> (world -> Picture)           -- ^ A function to convert the world a picture.
        -> (Event -> world -> world)    -- ^ A function to handle input events.
        -> (Float -> world -> world)    -- ^ A function to step the world one iteration.
                                        --   It is passed the period of time (in seconds) needing to be advanced.
        -> IO ()
Run Code Online (Sandbox Code Playgroud)

(直接从http://hackage.haskell.org/packages/archive/gloss/1.7.4.1/doc/html/Graphics-Gloss-Interface-Pure-Game.html复制)

这是world我正在使用的类型:

data Game = Game
  { levelNumber  :: Int,
    currentLevel :: Level Square,
    won          :: Bool }
Run Code Online (Sandbox Code Playgroud)

其中Levels包含当前级别的块.我正在Game使用类似的东西读取(实际上还没有实现广义的,但这基本上就是文件名参数):

startGame = do
  lvl <- readFile "levels/level001.lvl"
  let lvl' = parseLevel lvl
  return $ Game 1 lvl' False
Run Code Online (Sandbox Code Playgroud)

所以,我的困难是由于更新功能而产生的play.如果我只是在单个级别上操作,我可以很容易地获取Game并生成一个Picture(和一个Game等),而不必从文件系统中读取任何数据,但是因为我在文件中间加载了文件中的级别.游戏,我不知道如何避免制作我Game的所有IO Game.也许在这种情况下这是不可能的,也许这是有充分理由的?我始终在运行Game,从文件中提取,但是我不知道这是否是可以避免的,在任何给定的点,如果是,我想避免它.

Ben*_*ach 3

我最终使用了Graphics.Gloss.Interface.IO.GameplayIO的Gloss 。我需要更改我的几个函数以对纯数据类型进行操作并将它们包装在 monad 中输出。以下是我必须更改的类型:IO

worldToPicture :: World -> IO Picture
eventHandler   :: Event -> World -> IO Picture
stepWorld      :: Float -> World -> IO World 
Run Code Online (Sandbox Code Playgroud)

在大多数情况下,这只会在我当前现有的功能中添加一些return功能,但最终会添加很多功能(例如即时保存、加载新关卡、使用 BMP 文件进行图形等)。我还能够保留几乎所有当前现有的代码,IO因为新函数仍然采用纯数据类型作为参数。它最终成为一个非常简单的重构并完美地解决了我的问题。