我正在尝试在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
?
答案 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)