在Haskell中使用IO的游戏循环

时间:2017-05-04 02:42:11

标签: haskell game-loop

我正在尝试在Haskell中编写一个非常简单的游戏。 我有这个循环,这是最后一部分,我真的不知道该怎么做。当然它是一个循环,所以它必须自己运行。

gameLoop :: User -> IO ()
gameLoop initUser = displayPosition initUser >> gameLoop (applyAction initUser)
  where
    applyAction :: UserAction
    applyAction = maybe id (unsafePerformIO (fmap getUserAction getLine))

getUserAction :: String -> Maybe UserAction是一个在地图中查找字符串并返回UserAction :: User -> User的函数。然后我做了一些丑陋的解包(unsafePerformIO),我不知道要绕过它。

我认为这应该运行,因为我的类型似乎是正确的,但它仍然没有。

它说:

maybe is applied to too few arguments  AND
couldn't match a1 -> a0 -> a0 with actual type Maybe UserAction, because unsafePerformIO is applied to too few arguments.

我不明白这些错误。任何人都可以解释如何解决这些最后的问题,或者如何摆脱unsafePerformIO

1 个答案:

答案 0 :(得分:1)

为了不使用unsafePerformIO,请使用IO。试试这个:

getUserAction <$> getLine :: IO (Maybe UserAction)

<$>fmap。这是一个IO操作,可以让用户执行操作。然后,使用fromMaybe设置deafult值(在本例中为id),将Maybe UserAction转换为UserAction

getAction :: IO UserAction
getAction = fromMaybe id . getUserAction <$> getLine

请注意,a . b <$> c(a . b) <$> c,而不是a . (b <$> c)

现在您可以在主循环中一次性使用此功能:

gameLoop :: User -> IO ()
gameLoop initUser = displayPosition initUser >> getAction >>= \userAction -> gameLoop (userAction initUser)

或使用do - 表示相同的符号:

gameLoop :: User -> IO ()
gameLoop initUser = do
  displayPosition initUser
  userAction <- getAction
  gameLoop (userAction initUser)